#1,184 – Where Data Templates Are Used, part II

A data template is typically set as the value of the ContentTemplate property of a ContentControl or the ItemTemplate property of an ItemsControl.

The ContentTemplate and ItemTemplate properties are typically used as follows:

  • The ContentTemplate is used as the ContentTemplate of a ContentPresenter, which is itself contained in the control’s control template
  • The ItemTemplate is used as the ContentTemplate for each item presented by an ItemsPresenter (e.g. used as ContentTemplate for a ListBoxItem).

Below is a fragment of the default control template for a Label. You can see that it contains a ContentPresenter that has its ContentTemplate set to the ContentTemplate of the parent control.

                    <ControlTemplate TargetType="{x:Type Label}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>

#1,183 – Where Data Templates Are Used

Data templates dictate how bound data is mapped to one or more control.  A data template can be used in two places:

  • As value of ContentTemplate property for a ContentControl  (e.g. a Label)
  • As value of ItemTemplate property for an ItemsControl  (e.g. a ListBox)

Here’s an example of a DataTemplate used as the ContentTemplate for a Label:

<Label Name="lblPerson" Content="{Binding}">
    <Label.ContentTemplate>
        <DataTemplate>
            <Border BorderThickness="2" BorderBrush="DarkBlue">
                <StackPanel Orientation="Vertical">
                    <StackPanel Orientation="Horizontal">
                        <Label Content="{Binding Path=FirstName}"/>
                        <Label Content="{Binding Path=LastName}" FontWeight="Bold"/>
                    </StackPanel>
                    <Label Content="{Binding Path=BirthYear}" FontStyle="Italic"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Label.ContentTemplate>
</Label>

Here’s an example of a DataTemplate used as the ItemTemplate for a ListBox:

  <ListBox Margin="15" Width="270" Height="320"
         ItemsSource="{Binding ActorList}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Image Source="{Binding Image}" Height="80"/>
                    <StackPanel Margin="5">
                        <TextBlock Text="{Binding FullName}" FontSize="12" FontWeight="Bold"/>
                        <TextBlock Text="{Binding Dates}"/>
                        <TextBlock Text="{Binding KnownFor}" Margin="0,5,0,0" FontStyle="Italic"/>
                    </StackPanel>
                    <Label Content="Dead Fred !" Foreground="Red"
                           FontWeight="Bold"
                           Visibility="{Binding Converter={StaticResource deadFredConverter}}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

#968 – ListBox Data Binding Basics, part V

If you want to display the items in a ListBox using something more than a simple string, you can set the ItemTemplate of the ListBox and define the exact layout of each item.  When you set the ItemTemplate, you don’t set the DisplayMemberPath property.  DisplayMemberPath simple defines the template for each item in the ListBox to be a TextBlock that displays a single string.

In the example below, we set an item template for a ListBox that binds to a collection of Actor objects so that we display an image and some information about the actor, for each item.

        <ListBox Margin="15" Width="250" Height="250"
                 ItemsSource="{Binding ActorList}"
                 SelectedItem="{Binding SelectedActor}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Image}" Height="80"/>
                        <StackPanel Margin="5">
                            <TextBlock Text="{Binding FullName}" FontSize="12" FontWeight="Bold"/>
                            <TextBlock Text="{Binding Dates}"/>
                            <TextBlock Text="{Binding KnownFor}" Margin="0,5,0,0" FontStyle="Italic"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

968-001

#178 – A Control Can Have Both a Control Template and A Data Template

A control template dictates a control’s constituent controls, while a data template dictates how bound data will be rendered.  A control can actually have both types of templates at the same time.

In the XAML fragment below, we specify a Label‘s Template property, setting it to a ControlTemplate.  (This is actually the default control template for a Label).

We also specify the label’s ContentTemplate as a DataTemplate.  This template dictates how we’ll render the actual data (content) bound to the Label.

        <Label Name="lblPerson" Content="{Binding}">
            <Label.Template>
                <ControlTemplate TargetType="{x:Type Label}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Label.Template>
            <Label.ContentTemplate>
                <DataTemplate>
                    <Border BorderThickness="2" BorderBrush="DarkBlue">
                        <StackPanel Orientation="Vertical">
                            <StackPanel Orientation="Horizontal">
                                <Label Content="{Binding Path=FirstName}"/>
                                <Label Content="{Binding Path=LastName}" FontWeight="Bold"/>
                            </StackPanel>
                            <Label Content="{Binding Path=BirthYear}" FontStyle="Italic"/>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </Label.ContentTemplate>
        </Label>

#176 – Two Kinds of Templates

In WPF, there are two different kinds of templatescontrol templates and data templates.

Control templates allow you to exactly specify the visual tree of a control, i.e. its constituent controls.  The example below shows a Button control being constructed out of a Button and two Label controls.

        <Button Name="btnWithTemplate" Content="Recreate Me" Foreground="Blue">
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <StackPanel Orientation="Horizontal">
                        <Label Content="**" Foreground="{TemplateBinding Foreground}"/>
                        <Button Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"/>
                        <Label Content="**" Foreground="{TemplateBinding Foreground}"/>
                    </StackPanel>
                </ControlTemplate>
            </Button.Template>
        </Button>

 

Data templates allow you to specify how a bound data object will be mapped to one or more controls.  The example below maps properties of a Person object to several labels.

        <Label Name="lblPerson" Content="{Binding}">
            <Label.ContentTemplate>
                <DataTemplate>
                    <Border BorderThickness="2" BorderBrush="DarkBlue">
                        <StackPanel Orientation="Vertical">
                            <StackPanel Orientation="Horizontal">
                                <Label Content="{Binding Path=FirstName}"/>
                                <Label Content="{Binding Path=LastName}" FontWeight="Bold"/>
                            </StackPanel>
                            <Label Content="{Binding Path=BirthYear}" FontStyle="Italic"/>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </Label.ContentTemplate>
        </Label>