Bookmark and Share Share...    Subscribe to this feed Feed   About Christian Moser  

Data Templates


Data Template are a similar concept as Control Templates. They give you a very flexible and powerful solution to replace the visual appearance of a data item in a control like ListBox, ComboBox or ListView. In my opinion this is one of the key success factory of WPF.

If you don't specify a data template, WPF takes the default template that is just a TextBlock. If you bind complex objects to the control, it just calls ToString() on it. Within a DataTemplate, the DataContext is set the data object. So you can easily bind against the data context to display various members of your data object

DataTemplates in Action: Building a simple PropertyGrid

Whereas it was really hard to display complex data in a ListBox with WinForms, its super easy with WPF. The following example shows a ListBox with a list of DependencyPropertyInfo instances bound to it. Without a DataTemplate you just see the result of calling ToString() on the object. With the data template we see the name of the property and a TextBox that even allows us to edit the value.

<!-- Without DataTemplate -->
<ListBox ItemsSource="{Binding}" /> 
<!-- With DataTemplate -->
<ListBox ItemsSource="{Binding}" BorderBrush="Transparent" 
            <Grid Margin="4">
                    <ColumnDefinition Width="Auto" SharedSizeGroup="Key" />
                    <ColumnDefinition Width="*" />
                <TextBlock Text="{Binding Name}" FontWeight="Bold"  />
                <TextBox Grid.Column="1" Text="{Binding Value }" />

How to use a DataTemplateSelector to switch the Template depending on the data

Our property grid looks nice so far, but it would be much more usable if we could switch the editor depending on the type of the property.

The simplest way to do this is to use a DataTemplateSelector. The DataTemplateSelector has a single method to override: SelectTemplate(object item, DependencyObject container). In this method we decide on the provided item which DataTemplate to choose.

The following exmple shows an DataTemplateSelector that decides between tree data templates:

public class PropertyDataTemplateSelector : DataTemplateSelector
    public DataTemplate DefaultnDataTemplate { get; set; }
    public DataTemplate BooleanDataTemplate { get; set; }
    public DataTemplate EnumDataTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, 
               DependencyObject container)
        DependencyPropertyInfo dpi = item as DependencyPropertyInfo;
        if (dpi.PropertyType == typeof(bool))
            return BooleanDataTemplate;
        if (dpi.PropertyType.IsEnum)
            return EnumDataTemplate;
        return DefaultnDataTemplate;
<Window x:Class="DataTemplates.Window1"
        <!-- Default DataTemplate -->
        <DataTemplate x:Key="DefaultDataTemplate">
        <!-- DataTemplate for Booleans -->
        <DataTemplate x:Key="BooleanDataTemplate">
        <!-- DataTemplate for Enums -->
        <DataTemplate x:Key="EnumDataTemplate">
        <!-- DataTemplate Selector -->
        <l:PropertyDataTemplateSelector x:Key="templateSelector"
              DefaultnDataTemplate="{StaticResource DefaultDataTemplate}"
              BooleanDataTemplate="{StaticResource BooleanDataTemplate}" 
              EnumDataTemplate="{StaticResource EnumDataTemplate}"/>
        <ListBox ItemsSource="{Binding}" Grid.IsSharedSizeScope="True" 
                 ItemTemplateSelector="{StaticResource templateSelector}"/>

How to react to IsSelected in the DataTemplate

If you want to change the appearance of a ListBoxItem when it is selected, you have to bind the IsSelected property of the ListBoxItem. But this is a bit tricky, you have to use a relative source with FindAcestor to navigate up the visual tree until you reach the ListBoxItem.

<DataTemplate x:Key="DefaultDataTemplate">
    <Border x:Name="border" Height="50">
        <DataTrigger Binding="{Binding RelativeSource=
            {RelativeSource Mode=FindAncestor, AncestorType=
                {x:Type ListBoxItem}},Path=IsSelected}" Value="True">
            <Setter TargetName="border" Property="Height" Value="100"/>

Last modified: 2009-10-08 16:50:58
Copyright (c) by Christian Moser, 2011.

 Comments on this article

Show all comments
Commented on 12.August 2009
This is truly awesome article. It helped me a lot and it gave me good ideas.
Commented on 2.November 2009
THANK YOU! I'd been searching to try and work out how to use IsSelected with a custom source for a while now. Thank you again!
Commented on 5.November 2009
This is a good article. I made same like this.using this article
Commented on 18.November 2009
I'm really stuck here with my listbox datatemplate:

I have a listbox where its datatemplate is a custom control
The lsitbox is bind to a datatable.
The datatable contains a integer GenderID (integer)
The customcontrol contains several textboxes and a combobox (gender)
All controls in the customcontrols are xaml binded and wotk perfectly, except for the combobox.
The problem is that the IstemsSource for the combobox is loaded after the control is initialized in the codebehind, meaning that the selectedvalue binding in xaml doesn't work.
The ItemsSource of the combobox is a datatable with 2 fields (ID (integer) & Gender(string)).
My Code:
'Fill the datatable
Dim oTBL As DataTable = GetGenderTBL()
Dim oBind As New Binding

.DataContext = oTBL
.DisplayMemberPath = "Gender"
.SelectedValuePath = "ID"
.SetBinding(ItemsControl.ItemsSourceProperty, oBind)
End With

Combo xaml:
<ComboBox Name="LstGender" Grid.Row="0" Grid.Column="7"
SelectedValue="{Binding Path=GenderID}"></ComboBox>

When running, the combobox list contains the items from the gender table, but no item is selected, the binding with Listbox GenderID doesn't work.

How can I load the combo ItemsSource before the controls in the listbox item are binding ?


Commented on 7.December 2009
awesome !
Commented on 9.December 2009
Nice to read...... ThankQ.
Commented on 10.December 2009
Seems a nice article.It would be Great,if more explanation is given,especially for the beginners.
Commented on 15.December 2009
I think I just decided to learn WPF...
Commented on 11.February 2010
Hi Christian,
Thank you very much, i got very good basics of WPF, it is really helpfull, i really appreciate your work.Thank you, could you give me guideline how to study WCF bascis, you can send to my mail id thank you again, i appreciate your work.
Commented on 11.March 2010
Very helpful article and I would further appreciate if you give the UI prinout before and after the application of the template. Thank you.
Commented on 20.April 2010
how can i use TreeView control to show SQL-database data in hierarchical view using c sharp.. please help me here because am working on windows from application project . iit's my graduation project.
Commented on 21.June 2010
This is a poor example. Where is the code behind? Where is the binding? What is this magic data you are adding to the list view?
Commented on 22.June 2010
This is a poor example. Where is the code behind? Where is the binding? What is this magic data you are adding to the list view?
Commented on 22.June 2010
This is a poor example. Where is the code behind? Where is the binding? What is this magic data you are adding to the list view?
Commented on 28.June 2010
Commented on 23.July 2010
Mr Confused,

Before you make conclusion, you'd better finish the whole article and then you will find sample solution for download in the end...
Commented on 24.August 2010
Its really very good information about data templates.
Commented on 1.October 2010
Great article, just what I was looking for. Great web site.
Commented on 9.November 2010
Commented on 9.November 2010
Worst discussion...lost interest in WPF
Commented on 9.November 2010
No Hemanath...It is not like that...It is really worth reading...WPF rocks...
Commented on 27.November 2010
Thank you, this really saved me a lot of time plowing though Hubers WPF Handbook. It is a worthy read, but I need a few results now.
Commented on 15.December 2010
I downloaded the sample and all it has it a bunch of checkboxes and textbox, i don't see any datatemplaing in the working...did you upload the wrote source codes?
Commented on 10.February 2011
Wow, I worked for a very long time on how to put together a dynamic property editor, and you make it look so easy. The key was Grid.IsSharedSizeScope and ColumnDefinition.SharedSizeGroup. Well done and thanks!
Commented on 3.March 2011
good chaka...
Commented on 30.March 2011
truely awesome, I have been looking for this functionality for a long time, I will put it into test and come back to you
Commented on 30.March 2011
Hi, I tried you method, all the text content are not rendered(the TextBlock showing nothing, even I place a button and bind Name for the content, still nothing). I am sure there is data, and before using data template, it's showing.

&lt;DataTemplate x:Key=&quot;DefaultDataTemplate&quot;&gt;
&lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
&lt;tree:RowExpander /&gt;
&lt;CheckBox IsChecked=&quot;{Binding Selected}&quot; /&gt;
&lt;Image Height=&quot;16&quot; Margin=&quot;2, 0, 5, 0&quot; Source=&quot;{Binding Converter={StaticResource TaskImageConverter}}&quot; Width=&quot;16&quot; /&gt;
&lt;TextBlock Style=&quot;{StaticResource TaskItemStyle}&quot; Text=&quot;{Binding Name}&quot; /&gt;
&lt;my:ResultCellTemplateSelector x:Key=&quot;templateSelector&quot;
DefaultDataTemplate=&quot;{StaticResource DefaultDataTemplate}&quot;/&gt;

&lt;tree:TreeList x:Name=&quot;tlResults&quot;&gt;
&lt;GridViewColumn Width=&quot;500&quot; Header=&quot;Name&quot; CellTemplateSelector=&quot;{StaticResource templateSelector}&quot;&gt;
&lt;GridViewColumn Header=&quot;Size&quot; Width=&quot;90&quot; DisplayMemberBinding=&quot;{Binding Converter={StaticResource FileSizeConverter}}&quot; /&gt;

Commented on 30.March 2011
sorry, it's my mistake, I used the template from another control. It's working fine now, thank you very much!
Commented on 15.April 2011
This is the best PropertyGrid Tutorial I found. The best part is,
it also have code to select DataTemplate depend on DataType of each class property: bool use BooleanDataTemplate which is a checkbox; Enum use EnumDataTemplate which is a combobox.
I also like go a little further, add custom type: lookup, which will show as dropdown list, but the value list come from database. e.g.
property name: car manufacturere, value come from &quot;SELECT LOOKUP_VALUE FROM LOOKUP WHERE LOOKUP_KEY = 'CAR_MFG'&quot;, which will return a list like: Toyota, Ford, Nissan, Honda, VW, BMW, ...
If I have &gt; 1 lookup properties, how I can speciafy them? LookupDataTemplate1, LookupDataTemplate2, ..., then how to specify them in XAML Resources. and all DataTemplate are pre-defined in XAML, how I can do it in this case.
similar to EnumToListConverter, How I can create LookupmToListConverter1, LookupmToListConverter2?

Thank you,

Commented on 21.April 2011
I run example solution with VS 2010 and .NET 4. It starts but when scrolling I am getting following error:

'' is not a valid value for property 'ClickMode'.

Same for 'FlowDirection', 'HorizontalAlignment, ecc.
Commented on 14.June 2011
@Mikhail: I get this Error while starting.
Try this with the Property DependencyPropertyInfo.Value in DependencyPropertyInfo.cs:
set { try { _element.SetValue (_descriptor.DependencyProperty, value); } catch { } }

I suppose the error occures, because the Comboboxes have no item selected...
Commented on 15.June 2011
Really nice articles

E-Mail (optional)