Custom data and dynamic templates in WPF


This blog describes how TemplateSelector in WPF can be used to dynamically modify contents of the UI. This is particularly useful in a common scenario many ISV's need to support: ability of 3rd parties and users to extend the ISV's data model with their own data columns.


For example, the original application may include a Product table with some columns (e.g. Id, Name, etc.). However, application's users may want to extend that definition to include additional columns. One of the issues that presents is using the data in UI: the UI provided by the ISV obviously has no notion of the new data columns. WPF, through template selector functionality allows the ISV to include these items in their UI.


One of the options on data binding is the specification of a template selector. Template selector is a custom class derived from DataTemplateSelector, which implements a method returning a DataTemplate given reference to the data that needs to be presented. The method can return an existing data template but it can also construct a new data template dynamically and return it. It is the last option that is particularly useful in the ISV scenario. The custom selector can dynamically discover the new columns added by the user, possibly collect additional meta-data about them (from SQL or some other proprietary mechanism used by the ISV) and return a data template, which provides a mapping of the data columns to WPF UI elements.


The attached sample shows how this can be done. For simplicity's sake the sample generates all its source data. Note that the recommended way of creating the new data template is by constructing xaml and using XamlReader. (The alternative, using the DataTemplate class, populating it with data, etc. is not recommended).


 

DynamicDataTemplate.zip

Comments (3)

  1. Ben Lowe says:

    Hi,

    As a WPF/Silverlight UX Designer I love the power of ControlTemplates and DataTemplates but as you point out (the only Microsoft blog that I've come across to do so, well done), us ISV often don't know at design time what data our individual customers will configure their systems to be displaying at run time.

    Starting off with a simple case of populating a grid (I'm actually working on doing this with the Silverlight DataGrid) I will need to set the DataGridTemplateColumn.CellTemplate and DataGridTemplateColumn.CellEditingTemplate to represent the data as I require.  Lets take Scott Morrison's example of adding a TextBlock for the normal template and a DatePicker to the editing template.  At design time he simply binds it up to the "birthday" data object and it all works lovely (or at run time but it was still hardcoded at design time in the code), in your case you've hardcoded the binding to MyName.

    Ideally I would want to set up a couple of generic DataTemplates called something like "dateReadOnlyDataTemplate" and "dateEditDataTemplate" that aren't bound up at design time.  At run time there would be some code that knows it needs to add a date column, gets the two DataTemplates and somehow sets the binding within each DataTemplate to that of the data object it should be bound to before attaching them to the DataGridTemplateColumn.

    How would we go about doing that?  Is it possible, in  code,  to convert a DataTemplate resource into a string, replace a placeholder for the binding path and then use the XamlReader to load back up the properly bound version?

    We've spent the last two years building up the designer - developer split so i can work almost exclusively in XAML leaving our developers to concentrate on the business logic.  Any creation of templates in code (like in your example) ruins all of that seperation and means the designers will have to learn C#, or even worse, the developers would end up designing the UX!

    I'm guessing some of this might be trickier to do in Silverlight so some hints on a WPF only version would be equally appreciated.

    Thanks

    Ben

  2. aarondh says:

    I would just like to point out an implementation of the DataTemplateSelector that I created a while back that really helps with the ability to display custom user data classes.  The code is on codeplex at http://www.codeplex.com/ComplexDataTemplates

Skip to main content