Styles and Templates - How's everything related?

People who are new to the platform often have these questions about styles and templates (and a related concept, resources):

 

What is a Resource?

In the simplest terms, a resource is a reusable object. For example, the following SolidColorBrush is declared and used as a resource:

<Window . . .>

  <Window.Resources>

    <SolidColorBrush x:Key="DarkColorBrush" Color="#454" />

  </Window.Resources>

  <StackPanel>

    <Button Height="40" Width="40" Content="Test"

            Background="{StaticResource DarkColorBrush}"/>

    <TextBlock Text="Test"

               Foreground="{StaticResource DarkColorBrush}"/>

  </StackPanel>

</Window>

What is a Style?

In the simplest terms, a Style is a set of property values that can be shared across multiple instances of a type.

<Window . . .>

  <Window.Resources>

    <Style TargetType="TextBlock">

      <Setter Property="FontFamily" Value="Comic Sans MS"/>

      <Setter Property="FontSize" Value="14"/>

    </Style>

  </Window.Resources>

  <StackPanel>

        <!--All TextBlocks instantiated here will have

        FontSize of 14 and FontFamily of Comic Sans MS-->

  </StackPanel>

</Window>

That’s what a Style is in the simplest terms; a Style can be a lot more than just a bunch of property values. In addition to Setters, within a Style there can be Triggers, EventTriggers, EventSetters and Resources. You can essentially “package” all those things up into a Style so that they can be applied to multiple instances of an object.

How are Styles and Resources related?

Styles are most often created and used as resources. Note that a Style does not have to be a resource. You can have an “inline” Style, i.e., you can do something like this:

<Button Content="Inline Style">

  <Button.Style>

    <Style TargetType="Button">

      <Setter Property="FontFamily" Value="Comic Sans MS"/>

      <Setter Property="Width" Value="100"/>

    </Style>

  </Button.Style>

</Button>

But it usually makes sense for a Style to be a Resource. You can always give a Style an x:Key:

<Style TargetType="TextBlock" x:Key="myTextBlockStyle">

  <Setter Property="FontFamily" Value="Comic Sans MS"/>

  <Setter Property="FontSize" Value="14"/>

</Style>

And then do this:

<TextBlock Style="{StaticResource myTextBlockStyle}">TextBlock with Style</TextBlock>

What is a ControlTemplate?

The ControlTemplate of a control defines the structure and appearance of the control. Most controls have appearance and behavior. Consider a button: the behavior is the Click event that gets raised in response to a click and the default appearance (defined by the default ControlTemplate) is the raised rectangular area you can press.

You can use style setters to set property values to affect the look of a control. But to change the structure of a control or to set property values on the components that comprise a control, you need to use a ControlTemplate.

What is a DataTemplate?

A DataTemplate defines the structure and appearance of data. DataTemplates are most commonly used with data-bound ItemsControls (ListView, ListBox, TreeView, etc). However, other controls can use DataTemplates too.

How are DataTemplates and ControlTemplates related?

One way to think about it is that the “content” of a control is the data. To define the appearance of the data, you use a DataTemplate. To define the appearance of a control, set the control properties directly, using a Style, or consider using a ControlTemplate.

In general, DataTemplates are used a lot more often than ControlTemplates. When you are about to write a custom control, think about whether you can use a ControlTemplate to do the trick. When you want to affect how your data/information appears, use DataTemplates.

As an illustration, take a look at the following example:

 

This is a data-bound ListBox that uses a DataTemplate. For demonstration purposes this DataTemplate is declared inline:

<ListBox HorizontalContentAlignment="Stretch"

         ItemsSource="{Binding Source={StaticResource myTasks}}">

  <ListBox.ItemTemplate>

    <DataTemplate>

      <DataTemplate.Resources>

        <Style TargetType="TextBlock">

          <Setter Property="FontSize" Value="18"/>

          <Setter Property="HorizontalAlignment" Value="Center"/>

        </Style>

      </DataTemplate.Resources>

      <Grid>

        <Ellipse Fill="Silver"/>

        <StackPanel>

  <TextBlock Margin="3,3,3,0"

                     Text="{Binding XPath=@Name}"/>

          <TextBlock Margin="3,0,3,7"

                     Text="{Binding XPath=@Priority}"/>

        </StackPanel>

      </Grid>

    </DataTemplate>

  </ListBox.ItemTemplate>

  <!--This defines the look of each ListBoxItem-->

  <ListBox.ItemContainerStyle>

    <Style>

      <Setter Property="Control.Width" Value="100"/>

      <Setter Property="Control.Margin" Value="5"/>

    </Style>

  </ListBox.ItemContainerStyle>

</ListBox>

The data is set up this way:

<XmlDataProvider x:Key="myTasks" XPath="Tasks/Task">

  <x:XData>

  <Tasks xmlns="">

  <Task Name="Groceries" Priority="2" Type="Home">

  <Description>Pick up Groceries and Detergent</Description>

  </Task>

  <!-- other Tasks -->

    </Tasks>

  </x:XData>

</XmlDataProvider>

We managed to change the appearance of the content of the ListBox quite a bit that way. We were defining the look of the data so we did not need to use a ControlTemplate.

As I mentioned before, a ControlTemplate defines the structure and appearance of a Control while a DataTemplate defines those of the content of a Control. Underlying both of those concepts is the concept that you can take a tree of elements and make that become the visual representation of the “thing” you’re concerned about, the “thing” being your control or your data. As my attempt to show just that, I took the definition of the DataTemplate, tweaked it a bit, and used it as the ControlTemplate of a Button:

<Button Width="100" FontSize="18" Content="Test">

  <Button.Template>

    <ControlTemplate TargetType="Button">

      <Grid>

        <Ellipse Fill="Silver"/>

        <ContentPresenter HorizontalAlignment="Center"/>

      </Grid>

    </ControlTemplate>

  </Button.Template>

</Button>

The Button looks like this:

One thing that’s worth mentioning is that you can define triggers and resources within the scope of your ControlTemplate or DataTemplate as well (so if you want to get very technical, it is not strictly just structure and appearance).

 

How are Styles related to DataTemplates and ControlTemplates?

As mentioned before, one way to think about a Style is as a tool to set properties. Controls have properties that are of type DataTemplate or ControlTemplate. Therefore, you can use a Style to set those properties as well. For example, instead of declaring the above ControlTemplate inline, you may do this:

<Style TargetType="Button">

  <Setter Property="Template">

    <Setter.Value>

      <ControlTemplate TargetType="Button">

        <Grid>

  <Ellipse Fill="Silver"/>

  <ContentPresenter HorizontalAlignment="Center"/>

        </Grid>

      </ControlTemplate>

    </Setter.Value>

  </Setter>

</Style>

In fact, you may notice that ControlTemplates are often set that way. DataTemplates can be set that way too but they are more commonly created and applied as resources. One of the reasons why it is not as common to create a “standalone” ControlTemplate is that ControlTemplates don’t have the notion of an implicit key. In other words, unlike Styles and DataTemplates, you cannot put the following in the resources section:

<!--This causes a compiler error.-->

<ControlTemplate TargetType="Button">

    . . .

</ControlTemplate>

This does not get applied to all Button types automatically. In fact, this gives you an error. If you create a “standalone” ControlTemplate that way, you must give it an x:Key and use it as a resource.

Of course, Style, DataTemplates, and ControlTemplates are also related in that you can think of them as all being part of the suite of features that let you create consistently good-looking apps… with style. ;P

Thanks for reading!

Tina

 

P.S. For further reading, check out these new docs in the SDK: Styling and Templating and Data Templating Overview.

About Us


We are the Windows Presentation Foundation SDK writers and editors.