Here is part 3 of Josh Twist's 10 part series on the reasons to consider WPF for your next desktop application, this part explores the topic of DataTemplates.

Earlier I introduced a series of posts entitled 10 reasons to consider WPF for your next desktop application. If you haven't read the intro yet, better head on back and read it first.

You could consider the power of this point to really be the combination of the previous two points (Rich Content Model and Databinding) but nonetheless, DataTemplates definitely deserve a reason of their own.

MSDN describes the DataTemplate thus:

"You use a DataTemplate to specify the visualization of your data objects. DataTemplate objects are particularly useful when you are binding an ItemsControl such as a ListBox to an entire collection. Without specific instructions, a ListBox displays the string representation of the objects in a collection. In that case, you can use a DataTemplate to define the appearance of your data objects. The content of your DataTemplate becomes the visual structure of your data objects."

A great description (which is why I stole it) but let's look at an example.

We're going to use the same simple form that we used in the Reason 2 example and pimp it up!

Example 1 - simple form

Pimp my listbox

In Reason 2 our listbox was simply bound to a collection of Book objects and therefore it simply called ToString (which I'd overridden).

<ListBox Name="_lstBooks" ItemsSource="{Binding}" />

I could have done this better by specifying the DisplayMemberPath and directly bound the display to the Name property. The advantage of this being that the ListBox would now receive notification when the Name property changes and update the listbox automatically. Nice.

<ListBox Name="_lstBooks" ItemsSource="{Binding}" Margin="3" DisplayMemberPath="Name"/>

But what if we want to exercise the power of the rich content model? For example, what if we wanted each item to display a tooltip with the author's name like so:

with a tooltip

Easy peasy, change the ItemTemplate of the ListBox to be a custom DataTemplate.

<ListBox Name="_lstBooks" ItemsSource="{Binding}" Margin="3">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" ToolTip="{Binding Author}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

That's just not pimped enough though really is it? Let's imagine we have a BookUrl property on the Book class that specified the Url of a picture. Now we can push our DataTemplate a bit harder.

<ListBox Name="_lstBooks" ItemsSource="{Binding}" Margin="3">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" ToolTip="{Binding Author}">
                <Image Source="{Binding BookUrl}" Width="50" Margin="5"/>
                <TextBlock Text="{Binding Name}" Margin="0,5,0,0"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

with a tooltip

Much better. But let's go further. What if we wanted a neat little bar to visualise the customer rating (score out of 5).

<ListBox Name="_lstBooks" ItemsSource="{Binding}" Margin="3">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" ToolTip="{Binding Author}">
                <Image Source="{Binding BookUrl}" Width="50" Margin="5"/>
                <StackPanel Margin="0,5,0,0" HorizontalAlignment="Stretch">
                    <TextBlock Text="{Binding Name}" />
                    <Border BorderBrush="Black" BorderThickness="1" Width="100" Height="20" Background="White"
                    SnapsToDevicePixels="True" HorizontalAlignment="Left">
                    <Viewbox Stretch="Fill">
                        <Border Width="5" BorderThickness="0">
                            <Rectangle Width="{Binding CustomerRating}" Fill="Orange"
                                 Height="10" HorizontalAlignment="Left"/>
                        </Border>
                    </Viewbox>
                    </Border>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Just like that.

with a little visualisation

Notice that the crux of this solution is that we bind the width of an orange rectangle to the customer rating. We then use a Viewbox to scale it up a bit and we're done.

Now this is cool. And notice that if I change the value of the Customer Rating, the bar automatically changes too!

that updates!

Hopefully you're starting to see just why I think WPF is such an awesome platform.

Why not have a play with the Reason 3 ClickOnce Sample.

IMPORTANT NOTE - the customer ratings used in these examples are totally random and do not necessarily reflect my, or anybody elses for that matter, actual opinion!

Originally Posted by Josh Twist on 17 Oct 2007 here.