WPF: The DataTemplate, choosing how your data will look like!

Posted on 3/5/2007 @ 1:21 AM in #Silverlight and WPF by | Feedback | 36466 views


This post is in continuation to an explanation on WPF Templates.

1. ControlTemplate - You use this, when you want to completely redefine the visual appearance of any control. Say, you don't want a radiobutton to look like a radiobutton - you want it to look like a smiley instead. Smiling means Checked, and Frowning means Unchecked. You could easily acheive this using ControlTemplate.

2. ItemsPanelTemplate - Is a rather simple kind of template, it lets you control the appearance of the "ItemsPanel" property defined by "ItemsControl" on elements such as ListBox or ComboBox.

3. DataTemplate - is probably the most common kind of template you will use. It lets you change how "Content" is rendered on any control. So if you have an object called "Customer" and you want to define a standard look and feel for "Customer" - you'd use DataTemplate.


Say, I have a class that looks a bit like this -

public class LocalTimes : List<LocalTime>

{

    public LocalTimes()

    {

        this.Add(new LocalTime("New York", DateTime.Now));

        this.Add(new LocalTime("Chicago", DateTime.Now.AddHours(-1)));

        this.Add(new LocalTime("Denver", DateTime.Now.AddHours(-2)));

        this.Add(new LocalTime("Los Angeles", DateTime.Now.AddHours(-3)));

    }

}

 

public class LocalTime

{

    private string place;

    private DateTime time;

 

    public LocalTime(string _place, DateTime _time)

    {

        place = _place;

        time = _time;

    }

 

    public DateTime Time

    {

        get { return time; }

        set { time = value; }

    }

 

    public string Place

    {

        get { return place; }

    }

}

Now, I wish to be able to represent this class in a DataBound UI. Say, I wish to DataBind it to a ListBox, I can easily acheive this in 2 steps

a) Define the ObjectDataProvider -

<Window x:Class="WPFApp.Window2"

 ... some other goo I took out ...

    xmlns:custom="clr-namespace:WPFApp"

    >

  <Window.Resources>

    <ObjectDataProvider x:Key="localTimes" ObjectType="{x:Type custom:LocalTimes}"/>

  </Window.Resources>

  <Grid>

  </Grid>

</Window>

b) Do the actual DataBinding -

<Grid>

  <ListBox

    ItemsSource="{Binding Source={StaticResource localTimes}}"

    >

  </ListBox>

</Grid>

 

This should work huh? Run the app, here is how it'd look like -

Hmm .. not quite!

What is missing is, I haven't specified, how the heck I'd like my UI to look like.

To specify, how an instance of "LocalTime" will render itself on a WPF UI, you will need to define a DataTemplate. So you need to do 2 more steps -

a) Define the DataTemplate under resources -

<DataTemplate x:Key="ShowTime" DataType="WPFApp.LocalTime">

  <StackPanel Margin="10">

    <Control Template="{StaticResource clockTemplate}" Width="120" Height="108" DataContext="{Binding Path=Time}"/>

    <TextBlock Text="{Binding Path=Place}" HorizontalAlignment="Center"/>

  </StackPanel>

</DataTemplate>

As you can note, in the above, in order to render the "Time" portion, I am using the "clockTemplate" that will render a databound DateTime to a clock that looks like this  -

The full source code for the clockTemplate can be found here.

b) Specify that we would like to render the ListBox using the specified DataTemplate as shown below -

<ListBox

  ItemsSource="{Binding Source={StaticResource localTimes}}"

  ItemTemplate="{StaticResource ShowTime}"

> 

</ListBox>

Great!

Now go ahead and run the app. Here is what you see !!

NEAT !!

So that is what you'd use a DataTemplate for. You specify in a DataTemplate, how you want your custom business objects will be rendered on the screen, and in doing so, you can use the full power of WPF.

Now, what if I wanted to align those clocks Horizontally? Hmm .. that'd be a job for the ItemsPanelTemplate.

Sound off but keep it civil:

Older comments..


On 1/28/2010 3:40:28 PM Dmitry said ..
This is an excellent post, everytime I forget how to use a DataTemplate I wind up coming here :)