BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Control Templates - Template Bindings

The one hundred and sixty-first part of the Windows Presentation Foundation Fundamentals tutorial describes template bindings. This type of binding allows a control template to use property values from the controls to which it is applied.

Template Bindings

In the previous article we started to look at how you can create control templates. These allow you to replace the visual tree of controls for a completely different look and feel, when compared to the standard items. We saw how to create and apply a basic template but did not consider how the properties of a control could affect the user interface.

To modify the visual tree generated by a template to reflect the control's property values, you must use template bindings. A template binding is a special type of data binding that allows you to reference the parent control, read its properties and apply their values. In some cases, you can use the values directly. In other situations you may need to apply value converters or additional formatting.

To demonstrate we need a sample solution. Create a new WPF application in Visual Studio, naming the project, "TemplateBindingDemo". Once ready, replace the XAML of the main window with the following:

<Window x:Class="TemplateBindingDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Template Binding Demo" Height="150" Width="350">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        
        <ProgressBar Name="MyPB" Height="30" />
        
        <ScrollBar Grid.Row="1" Orientation="Horizontal"
                   Maximum="{Binding ElementName=MyPB,Path=Maximum}"
                   Minimum="{Binding ElementName=MyPB,Path=Minimum}"
                   Value="{Binding ElementName=MyPB,Path=Value}"/>
    </Grid>
</Window>

The result is a window containing a ProgressBar and a ScrollBar. The Maximum, Minimum and Value properties of the scroll bar are bound to the matching progress bar members, so manipulating the scroll bar updates the progress bar automatically.

WPF TemplateBinding demo window

Adding a Template Binding

The syntax for a template binding is similar to that of a simple data binding. Use the TemplateBinding markup and the name of the source property, contained within a pair of braces {}.

{TemplateBinding source-property}

To demonstrate, let's create a template for the progress bar and add some template bindings. Start by adding the following Window.Resources section above the opening Grid tag. This defines a control template resource for progress bars that includes a standard progress bar and a text block. We'll use these elements to create controls that give both a graphical representation of progress and a numeric output.

<Window.Resources>
    <ControlTemplate x:Key="TextProgressBar" TargetType="ProgressBar">
        <Grid>
            <ProgressBar />
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
                        FontWeight="Bold" Foreground="Black"/>
        </Grid>
    </ControlTemplate>
</Window.Resources>

Update the progress bar control within the grid to apply the control template:

<ProgressBar Name="MyPB" Height="30" Template="{StaticResource TextProgressBar}"/>

If you run the program you will find that changing the scroll bar's value no longer updates the progress bar. The underlying control's properties are still being updated. However, the progress bar that you can see is the one generated by the template, which is not yet bound to any values.

To make the template's progress bar correctly show the control's values, we need to add three template bindings. These will bind the Value, Maximum and Minimum properties to the corresponding values of the parent control.

Update the progress bar within the control template to add the three template bindings:

<ProgressBar Value="{TemplateBinding Value}"
             Maximum="{TemplateBinding Maximum}"
             Minimum="{TemplateBinding Minimum}"/>

Run the program to see the results. The progress bar should now update correctly but the text block will remain empty.

Template Bindings with Value Converters

To enable the numeric display, we need to bind the Text property of the text block to the Value property from the control. The former is a string and the latter is a double-precision floating-point number. This means that a value converter or a string format must be employed. Unfortunately, the TemplateBinding markup is simplistic and does not permit you to specify these additional properties. However, TemplateBinding is the equivalent of a standard data binding that uses a relative source of TemplatedParent. We can use this syntax instead, specifying any value converter, formatting or other binding properties we require.

Let's bind the Text property of the TextBlock to its templated parent. Update the XAML for the control, as follows:

<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
           FontWeight="Bold" Foreground="Black"
           Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                          Path=Value,
                          StringFormat=0}"/>

Run the program to see the results. As you move the scroll bar, you should now see both the progress bar and the text block update to match the selected value.

WPF ProgressBar control template with value as text

28 May 2015