Jerry Nixon @Work: November 2008

Jerry Nixon on Windows

Wednesday, November 26, 2008

The value of Version 1.1

As agile processes reform the SLDC, expectations and deliverables converge. However, initial releases still have gaps. This is a software tautology: user acceptance arrives when the second release arrives. Version 1.0 is successful development. Version 1.1 is successful software.

Version 1.0 planning should include version 1.1 planning. Version 1.1 translates to user acceptance – software success's pinnacle measure. For project completion, stop at version 1.0. For successful software, push on for version 1.1.

Here's the deal. Version 1.0 can be great, but users rarely understand day-to-day impact of software until they use it day-to-day. It's not a sign of failure. On the contrary, it's a sign of partial success that users are exercising the application. It's the path to success.

So release – twice.


Simple Master/Details, Data Bound WPF Sample

It's time to stop ignoring WPF.

Before we do, let's be honest.

Five reasons WPF sucks:

  1. Using Blend (the WPF extra-Visual Studio design tool) is sloppy
  2. Editing raw XAML (like HTML for WinForms) is painfully slow
  3. Cool third party controls are few compared to WinForms
  4. The likelihood of major, forthcoming syntactic changes is high
  5. Samples and real world case studies are rare or absent

Five reasons WPF rocks:

  1. Done right, WPF can create an unmatched user experience
  2. Most WPF development ports to Silverlight without change
  3. Vector-based objects render faster and cleaner than bitmaps
  4. The .Net Framework is the same in WPF or WinForms
  5. Microsoft loves you when you adopt new technologies

Number 5 is real. Microsoft's WinForm support isn't even near sunset; the WinForms and WPF convergence is inevitable and imminent. Microsoft is investing heavily in WPF. Visual Studio 2010 is 100% WPF. That's amazing. Forthcoming applications will continue this.

Frankly, ignoring WPF is foolishness.

Consider HTML. Developers who watched HTML emerge, followed syntactic changes and enhancements more easily/slowly. XAML is young and simple. Follow it now. Train yourself on fundamental syntax and simple adoption of inevitable future enhancements.

WPF isn't going anywhere.  You don't need a blue badge to know WPF is strategic to Microsoft. It's growing in adoption, support, and power. The development experience is not as fast as WinForms today, but it's close. Eventually, they will be in parity.

Would I recommend WPF as a production platform?

Some argue WPF is the most future-oriented technology. Maybe. But developer velocity and maintenance is important. Today's WPF will be different than the next WPF. Deprecation of controls like ListView is an example. WPF needs to compliment other technologies, in my opinion. It would be difficult to recommend WPF as the sole LOB platform. But, that's me.

Now, let's create a simple application.

Here's what you are building -a simple master/detail form:

image

First create a WPF Application project. I called mine WpfApplication1. Clever, huh?

Second, spin up Northwind. Create a Linq to SQL class and add an Employee entity.

image 
Third, create an Employees.cs class. Here's the code: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
public class Employees
: ObservableCollection<Employee>
{
public Employees()
{
var _Result = from _Employee in
new DatabaseDataContext().Employees
select _Employee;
foreach (var item in _Result)
this.Add(item);
}
}
}

The reason for this class is so you can reference it as a self-filling DataContext from within the XAML. There are PLENTY of other ways to set the DataContext. This is just how I am doing it here. Honestly, I was trying to do it all without any Window1.xaml code behind. Once you understand DataContext, you can do whatever you want.


Forth, edit Window1.xaml. Here's the code: 



<Window x:Class="WpfApplication1.Window1"
x:Name="Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<DataTemplate x:Key="ListTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Path=Photo}"
Width="20" Stretch="UniformToFill" />
<Label Grid.Column="1"
Content="{Binding Path=FirstName}" />
<Label Grid.Column="2"
Content="{Binding Path=LastName}" />
</Grid>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<data:Employees />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox BorderThickness="0"
IsSynchronizedWithCurrentItem="True"
ItemTemplate="{StaticResource ListTemplate}"
ItemsSource="{Binding}" />
<StackPanel Grid.Column="1">
<Image Source="{Binding Path=Photo}"
Stretch="Fill" />
<Label Content="{Binding Path=FirstName}" />
<Label Content="{Binding Path=LastName}" />
<Label Content="{Binding Path=Title}" />
</StackPanel>
</Grid>
</Window>

Not much code, really?


Beautiful. Now hit F5.



There are a lot of neat things here:




  1. <DataTemplate> is used to display the user list and little photo. You can create templates on the page or in external files to be shared by pages/windows.


  2. xmlns:data="clr-namespace:WpfApplication1" is added so I can reference the classes in my project in the XAML of this window (like in the Window.DataContext).


  3. <Window.DataContext> references the structure for binding. The reason you add this in the XAML is the data types and sample data appear in the designer.


  4. IsSynchronizedWithCurrentItem="True" is the tag on the ListBox that indicates the SelectedItem of the control changes the CurrentItem on the CurrencyManger.



Have fun everyone!

Wednesday, November 19, 2008

November MSDN DevBash in Denver, Colorado

Yesterday was the MSDN DevBash. If you were there, thanks for attending. It was a standing room only event. And, looking back, I think the whole event was exceptional. I hope you all had a great time.
 

image

 
If you are looking for the code from my demo, it's in the next 5 or 6 posts on my blog, just scroll down! If you are wanting my PowerPoint slides, you need to email and for them. You can have them, I just don't want to post them here.

If you DID hear my presentation on using VSTO 3 in Visual Studio 2008 I would appreciate some feedback. I have a long way to go to be a great presenter, but I do love to present. I hope that came across. To those of you who came up to me after the presentation, thank you for your comments. 

But please, leave me feedback.

image

There is a lot to VSTO and we just covered a bit. I hope you walked away with a sense that VSTO is real, Office applications are plausible, and development doesn't have to be difficult. I also hoped you had fun.

My goals when I present are to:

  1. Present ideas not just lines of code
  2. Code. Code. Code. Prove it really works.
  3. Move fast, fill minds with content.
  4. Show cleaver tips and techniques.
  5. Make it as fun. Don't let them fall asleep.
  6. Be relevant. Apply it to the real world.

My new Business Cards - yeah!

What's worse than being asked "What do you do?" by people who outside the technical industry? My mom seriously thinks all I do is "make web pages" and "get Excel to print", but that's pretty inadequate.

It's worse being asked by people inside the technical industry. My role isn't typical. Explaining it is difficult. Mostly because of American Systems Group (ASG); we're not a typical organization.

ASG is a targeted. We're not interested in one industry. We're not interested in one technology. Although we are a Microsoft partner, our real purpose is to provide consultants to customers.

A contractor is not a consultant. They are sometimes used interchangeably. But we consider a contractor an hourly worker. A consultant, by contrast, is someone who cares about the customer and brings true expertise to the table.

We engage customers at a high level. We work to sell project vision. We work to build project awareness. We work to create project budgets and plans. And, we deliver the project through exhaustively vetted developers.

Our success rate is not the industry success rate. We don't allow projects to fail.

Many of us have worked together for more than 8 years. Others, less. But we are all dedicated to a few rare ideals: don't complain, don't BS, be great in your expertise, and deliver. Customers love it; who wouldn't.

My role in ASG is to help sell. But I also design project architecture. I also build reference implementations. I also help lead through the SDLC. I also develop software. I'm not a jack of all trades, what I do is just one comprehensive trade.

So, what do I do? I do a lot. Let's just call it "Principal Architect".
 
image
 
I'm looking for new developers. Developers with expertise (SQL, SharePoint, Workflow, WPF, Mobility, C#) - but only those dedicated to be great. You know the kind. They read MSDN. They play with BETAs. They tinker. They show up. A dying breed.

Developers like working for ASG because unlike those stupid Microsoft partners out there who treat technical artisans as employees, we treat them as valuable people. We pay better than anyone else, period. But we're demanding. It's great.

We don't force you to travel. We don't bait and switch. We don't beat you down. We don't beg for overtime. We treat you like you want to be treated. Why is this so rare? I really don't know. But it's rare. In fact, we may be the only one.

If you are a great developer. We might not have a place for you - not now. But let me keep your name and expertise in my "little black book". Our projects are interesting and challenging. If a fit arises, we'll call you and start the process.

If you have a project pending, starting, or in process - let me talk with you about it. Maybe we fit. We'll be honest about it. We can review architecture, coach you, mentor staff, bring in off shore, or just do it. You can decide, and we'll walk you through it.

Anyway, I just got my new card. Call me "Principal Architect" for now.

Use VSTO 3 to add an Action Pane to an Excel 2007 Workbook

This is too easy.

The Action Pane, sometimes called "Document Actions" (The unchangeable title of the actual window in Office), or the Right Panel, is just a User Control inside a docked window. You can use a WPF User Control or a WinForm User Control. You can use custom controls, third party controls, or anything you want.
 

<opinion>
If you choose to create applications in Office, good for you. A compelling reason is users understand Office and how to use it. Don't go putting things in places like the Action Pane which break the Office paradigm. If you do, you lose one major advantage of Office.
</opinion>

 
I have a User Control (in my sample) called UserControl1. Here's how to add it to the Action Pane area:
 

// create action pane

ActionPanel1 _Control;
_Control = new ActionPanel1();
Globals.ThisWorkbook.ActionsPane.Controls.Add(_Control);
_Control.Dock = System.Windows.Forms.DockStyle.Fill;
Globals.ThisWorkbook.ActionsPane.Visible = true;

Use VSTO 3 in Excel 2007 to trap Selection Changed in a ListObject

In my previous post I created a simple ListObject on a WorkSheet. But what if you wanted to know when the user selected a certain row? Could you use the events built into the ListObject to accomplish this? Yes. But those are difficult to use, I think. Instead, let's use the CurrencyManager which is nestled in the DataSource of the ListObject. Just watch:
 

// handle selection

System.Windows.Forms.CurrencyManager _CurrencyManager;
_CurrencyManager = _ListObject.BindingContext[_Source]
as System.Windows.Forms.CurrencyManager;

_CurrencyManager.CurrentChanged += delegate(object xsender, EventArgs xe)
{
// the selected record is in:
// (_CurrencyManager.Current as Database.Employee).EmployeeID;
};

Use VSTO 3 in Excel 2007 to add a data bound Table (ListObject)

The ListObject in Excel is a lot like a grid in WinForms. You can data bind to it. You can sort it, You can filter it. You can style it. You can do a lot. To create on one the fly (which is how I would recommend doing it - opposed to creating one in the designer) just use my sample as a guide. I'll put the new ListObject on Sheet1 in cell B:2. I'm using the Northwind Employees table in my sample.
 

 // get the data

var _Source = Database.Easy.Employees();

// create list

Microsoft.Office.Tools.Excel.ListObject _ListObject;
_ListObject = Globals.Sheet1.Controls.AddListObject(
Globals.Sheet1.Range["B2", System.Type.Missing], "SalesListObject");

// bind data

_ListObject.SetDataBinding(_Source, string.Empty,
new string[] { "FirstName", "LastName", "Title" });
_ListObject.AutoSetDataBoundColumnHeaders = true;

// expand the cols

Globals.Sheet1.Range["B:B", System.Type.Missing].EntireColumn.AutoFit();
Globals.Sheet1.Range["C:C", System.Type.Missing].EntireColumn.AutoFit();
Globals.Sheet1.Range["D:D", System.Type.Missing].EntireColumn.AutoFit();

Use VSTO 3 to add SmartTags to Excel 2007

SmartTags are simplified in VSTO 3 Service Pack 1. You get VSTO 3 Service Pack 1 when you download Visual Studio 2008 Service Pack 1 from Microsoft. Google for it. Once you have that, you can add a SmartTag very easily.

A SmartTag appears adjacent to cells when the content of the cell is recognized. Built-in Office SmartTags recognize things like Stock Symbols (see screen shot below) and Contact Names found in Outlook . Your SmartTag will need to be smart to identify values correctly.

image

To recognize content you add one, two, or one hundred terms. You can also point to a list. Or, you can use regular expressions to recognize string patterns. All are useful. You can mix them if you want. My demo uses regular expressions.

Remember, the purpose of a SmartTag is to let users do something. If you want a SmartTag, first you need one or more "Actions" which translate items in the menu users see when clicking on your tag (like "Stock quote on MSN MoneyCentral" shown above).

The sample below assumes all numbers in a Workbook refer to a record ID in the Northwind Employees table. Is this the type of SmartTag you want in your application? I hope not. But I think it gets the point across.

// smart tag actions

Microsoft.Office.Tools.Excel.Action _Action1;
_Action1 = new Microsoft.Office.Tools.Excel.Action(
"Lookup HR Record");
_Action1.Click += delegate(object xsender,
    Microsoft.Office.Tools.Excel.ActionEventArgs xe)
{
// do something;
};

Microsoft.Office.Tools.Excel.Action _Action2;
_Action2 = new Microsoft.Office.Tools.Excel.Action(
"Research Sales Orders");
_Action2.Click += delegate(object xsender,
    Microsoft.Office.Tools.Excel.ActionEventArgs xe)
{
// do something;
};

Microsoft.Office.Tools.Excel.Action _Action3;
_Action3 = new Microsoft.Office.Tools.Excel.Action(
"Terminate Employee");
_Action3.Click += delegate(object xsender,
    Microsoft.Office.Tools.Excel.ActionEventArgs xe)
{
// do something;
};

// smart tag

Microsoft.Office.Tools.Excel.SmartTag _SmartTag;
_SmartTag = new Microsoft.Office.Tools.Excel.SmartTag(
"jerry#demo", "SalesPerson Details");
_SmartTag.Expressions.Add(
new System.Text.RegularExpressions.Regex(@"\d"));
_SmartTag.Actions =
new Microsoft.Office.Tools.Excel.Action[]
{ _Action1, _Action2, _Action3 };

// add to workbook

Globals.ThisWorkbook.SmartTagOptions.EmbedSmartTags = true;
Globals.ThisWorkbook.VstoSmartTags.Add(_SmartTag);

Use VSTO 3 to create a PivotChart

If you have already created a PivotTable in Excel 2007, adding a PivotChart to it is easy. Assuming you have a local variable that refers to the PivotTable called "_PivotTable" this is all the code you need. The Pivot Chart will copy the column/row/measure settings of the PivotTable. Here's how you do it.
 

// create pivot chart

Globals.Sheet3.Shapes.AddChart(
XlChartType.xlColumnClustered,
System.Type.Missing,
System.Type.Missing,
System.Type.Missing,
System.Type.Missing).Select(System.Type.Missing);
Globals.ThisWorkbook.ActiveChart.SetSourceData(
_PivotTable.TableRange1,
System.Type.Missing);
Globals.ThisWorkbook.ShowPivotChartActiveFields = false;

Thursday, November 13, 2008

Use VSTO 3 to create a PivotTable in Excel 2007

I'm using LINQ to SQL to access Northwind here - you could use ADO.Net or whatever you want. The quick of it is this - I get the data, put the data in a table (ListObject) on Sheet2, then I create a PivotTable on Sheet3 using the ListObject on Sheet2 as the source data. Sheet1 is left empty.
 

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Excel;

// get data

EntityContext.NorthwindDataContext _db;
_db = new EntityContext.NorthwindDataContext();
var _Source = from _Order in _db.Orders
join _SalesPerson in _db.SalesPersons
on _Order.EmployeeID equals _SalesPerson.EmployeeID
select new
{
SalesPerson = _SalesPerson.FirstName
+ ' ' + _SalesPerson.LastName,
OrderId = _Order.OrderID,
OrderYear = _Order.OrderDate.Value.Year,
OrderCountry = _Order.ShipCountry,
OrderAmount = new Random().Next(500)
};

// create list

Microsoft.Office.Tools.Excel.ListObject _ListObject;
_ListObject = this.Controls.AddListObject(
Globals.Sheet2.Range["B2", missing], "ListObject1");
_ListObject.AutoSetDataBoundColumnHeaders = true;
_ListObject.SetDataBinding(_Source);

// create pivot

PivotCaches _PivotCaches;
_PivotCaches = Globals.ThisWorkbook.PivotCaches();

PivotCache _PivotCache;
_PivotCache = _PivotCaches.Create(
XlPivotTableSourceType.xlDatabase,
"ListObject1",
XlPivotTableVersionList.xlPivotTableVersion12);

Range _DestinationRange;
_DestinationRange = Globals.Sheet3.Range["B2", missing];

PivotTable _PivotTable;
_PivotTable = _PivotCache.CreatePivotTable(
_DestinationRange,
"PivotTable1",
missing,
XlPivotTableVersionList.xlPivotTableVersion12);
_PivotTable.DisplayFieldCaptions = false;
_PivotTable.TableStyle2 = "PivotStyleMedium2";

Globals.Sheet2.Name = "PIVOT_DATA";
Globals.Sheet3.Name = "PIVOT_TABLE";
Globals.Sheet3.Activate();

// setup columns/rows

(_PivotTable.PivotFields(4) as PivotField).Orientation
= XlPivotFieldOrientation.xlRowField;
(_PivotTable.PivotFields(1) as PivotField).Orientation
= XlPivotFieldOrientation.xlRowField;
(_PivotTable.PivotFields(3) as PivotField).Orientation
= XlPivotFieldOrientation.xlColumnField;

// measures

_PivotTable.AddDataField(
(_PivotTable.PivotFields(5) as PivotField),
"Sum Orders",
XlConsolidationFunction.xlSum).NumberFormat = "$#,##0";

Tuesday, November 4, 2008

The Service Agent API Separation Pattern

Although that is what Microsoft calls it, I call it the Service Proxy pattern. It is a very important and very valuable pattern.

This software pattern does not allow a client to access a service directly. Instead, it requires a proxy. A proxy can be simple or sophisticated. The pattern goal is to separate the service from the client.

In my experience, we implement a ServiceProxy class library. That library is the only project which is allowed to add a Web Reference or Service Reference (when we use WCF). It is shared across clients accessing the same service. Security and transformations are centralized. The service interface becomes stable – service signature changes minimally impact clients.

You only need to implement this pattern one time to fall in love with it.