WPFToolkit Grid formatting with dynamic columns

After having spent a day looking into presentation options of the WPF Toolkit grid, this write-up may help some people save time on deciding the best path forwards. Overall, I would recommend the Microsoft WPFToolkit grid for most purposes.

However, there are certain circumstances where this grid isn’t ready. This is what I intend to explain in this blog entry.

Requirements

For my current project, the primary requirements for the grid are listed below:

  • Req1: Display information from a DataSet
  • Req2: Correct formatting of numbers and dates, e.g. two decimal places or thousand separator or proper dates, e.g. 01/04/2009
  • Req3: Columns are added dynamically at run time
  • Req4: Copy data into Excel

Req1: Display information from a DataSet

This part is really easy, creating and binding the dataset works flawlessly in just a few line of code:

//put some information in a DataTable

DataTable dt = new DataTable();

dt.Columns.Add(“Mon”, typeof(float));

dt.Columns.Add(“Tue”, typeof(float));

float flt = 10.001F;

for (int nLoop = 0; nLoop < 10000; nLoop++)

{

  flt += 0.001F; // some increment to change values

  int nInt = Convert.ToInt32(flt) + nLoop + 1000;

  double dbl = (double)flt;

  dt.Rows.Add(flt + 1F, flt + 2F);

}

 

// Binding the DataTable to the Grid – easy stuff!

dataGrid1.ItemsSource = dt;

As with a previous blog, don’t forget to set the grid’s Virtualisation mode. Based on this above snippet, it’s straightforward to get things up and running quickly.

Req2: Correct formatting

Basically two approaches exist: XAML or code (C#). I tend to give preference to XAML and aim for less code intensive solutions

XAML

image

Essentially this is creating a DataTemplate to allow the column to apply the StringFormat method. While this is good being done at a column level, this does need the Path attribute set in the Binding expression to work correctly. For fixed DataSets, this is not a problem – however, if you add / remove columns from the underlying DataSet at runtime, then you can’t set the Path and StringFormat values in XAML.

Code

The simplest way is to get a call back from the Grid via the AutoGeneratedColumns property and place code in the event handler e.g.

AutoGeneratedColumns=”dataGrid1_AutoGeneratedColumns”

The event handler lets you execute code for formatting each time after you bind the columns via ItemsSource

//Change format as appropiate           
foreach (DataGridTextColumn dgtc in dataGrid1.Columns)
{
  Style rightAlignStyle = new Style(typeof(DataGridCell));

  Setter setter = new Setter();
  setter.Property = DataGridCell.HorizontalAlignmentProperty;
  setter.Value = HorizontalAlignment.Right;
  rightAlignStyle.Setters.Add(setter);

  dgtc.CellStyle = rightAlignStyle;

  //Depending on the column, set the format 
  dgtc.Binding.StringFormat = “{0:N0}”;

  dgtc.Binding.StringFormat = “{0:F2}”;
}

As you can see, 1 XAML line = several C# lines. A great article on styling the grid is XAML can be found at:

http://blogs.msdn.com/jaimer/archive/2009/01/20/styling-microsoft-s-wpf-datagrid.aspx

In addition, a good list of those formats can be found at idunno.org: http://idunno.org/archive/2004/14/01/122.aspx

Req3: Dynamic columns

Here’s where thing start to break and get complicated. Adding columns to the DataTable and re-attaching to the DataGrid’s ItemsSource is straight forward – the grid even shows the new columns with no problem.

The problem is formatting of those columns.

In XAML, unless you know all of the columns beforehand and simply hide them, then this is difficult to achieve. This would also lead to lots of XAML code if you have many columns.

Thus, at this point, the code solution is looking more promising as you can simply switch the format in the AutoGeneratedColumns event handler.

Req4: Copy to Excel

XAML

Selecting the rows when XAML is used works really well – you could click on any text or any white space in the grid and that row was selected. However, cells which have formatting applied (via TextBlock or StringFormat method) don’t automatically copy over to Excel.

Code

When the code solution is used, the selection of rows dramatically goes down in user experience – if you select any white space, the row isn’t selected, you have to click on the actual text.

Conclusion

What would be really nice is for the grid to allow some simple programmatic access that formats cells readily and not have some aspect break! I have found a good alternative, but don’t want to bias vendors, so drop me a line if you want the results.

Links

http://blogs.msdn.com/jaimer/archive/2009/01/20/styling-microsoft-s-wpf-datagrid.aspx

http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx?msg=2883597

http://sweux.com/blogs/smoura/index.php/wpf/2009/06/15/wpf-toolkit-datagrid-part-iv-templatecolumns-and-row-grouping/

http://wpf.codeplex.com/Thread/View.aspx?ThreadId=61051

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: