Bookmark and Share Share...    Subscribe to this feed Feed   About Christian Moser  


Control Templates

Introduction

Controls in WPF are separated into logic, that defines the states, events and properties and template, that defines the visual appearance of the control. The wireup between the logic and the template is done by DataBinding.

Each control has a default template. This gives the control a basic appearance. The default template is typically shipped together with the control and available for all common windows themes. It is by convention wrapped into a style, that is identified by value of the DefaultStyleKey property that every control has.

The template is defined by a dependency property called Template. By setting this property to another instance of a control template, you can completely replace the appearance (visual tree) of a control.



The control template is often included in a style that contains other property settings. The following code sample shows a simple control template for a button with an ellipse shape.

 
<Style x:Key="DialogButtonStyle" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Ellipse Fill="{TemplateBinding Background}"
                             Stroke="{TemplateBinding BorderBrush}"/>
                        <ContentPresenter HorizontalAlignment="Center"
                                          VerticalAlignment="Center"/>
                </Grid>            
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
 
 
 
<Button Style="{StaticResource DialogButtonStyle}" />
 
 

A Button without and with a custom control template

ContentPresenter

When you create a custom control template and you want to define a placeholder that renders the content, you can use the ContentPresenter. By default it adds the content of the Content property to the visual tree of the template. To display the content of another property you can set the ContentSource to the name of the property you like.

Triggers

{RelativeSource TemplatedParent} not working in DataTriggers of a ControlTemplate

If you want to bind to a property of a property on your control like Data.IsLoaded you cannot use a normal Trigger, since it does not support this notation, you have to use a DataTrigger.

But when you are using a DataTrigger, with {RelativeSource TemplatedParent} it will not work. The reason is, that TemplatedParent can only be used within the ControlTemplate. It is not working in the Trigger section. You have to use the {RelativeSource Self} instead.

What if a Binding working or a Setter is not applied when using a control template

There is something you need to know when setting a value of an element within a control template: The value does have a lower precendence as the local value! So if you are setting the local value in the constructor of the contained element, you cannot override it within the controltemplate. But if you use the element directly in your view, it will work. So be aware of this behavior!.

Here you can find more information about DependencyProperty value precendence: Dependency Property Value Precedence





Last modified: 2010-04-27 16:48:31
Copyright (c) by Christian Moser, 2011.

 Comments on this article

Show all comments
ouais
Commented on 29.July 2010
you people I really not getting why you are congrat this guy ! This site is uglying explaning WPF ! just good to run away and find real explanation from programmer !
i
Commented on 3.September 2010
seems really interesting thanks for your efforts to make this material available for us
Arjun
Commented on 3.September 2010
Nice one
Asha.MP
Commented on 12.October 2010
Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}"
in the above properties we can specify the colors also, what is the meaning of TemplateBinding in the above property??
siva
Commented on 19.October 2010
nice...
Praveen
Commented on 22.November 2010
Great Article , thanks for your efforts :)
bala
Commented on 24.January 2011
very nice.
sri
Commented on 21.February 2011
good one
prassanth
Commented on 24.March 2011
if u dont mind , can u thrown some light on visualstatemanager as well.. ?
Ankit
Commented on 17.April 2011
Many many thanks for this article...
Gurpreet Singh
Commented on 21.April 2011
Great explaination ! thanks
Tejas
Commented on 23.April 2011
Thanks buddy good articles

Janynne Gomes
Commented on 26.April 2011
Great explanation and i liked the figure, so clear!
anon
Commented on 4.May 2011
These comments are laughably fake.
Paras
Commented on 18.May 2011
Thanks, Nice explanation
Anon
Commented on 24.May 2011
Great. And where do i have to write the style-tag down, now?
Mayank
Commented on 1.June 2011
So Clear very nicely explained
jones
Commented on 14.June 2011
please show, how to focus and enable the elliptic button
bm
Commented on 9.July 2011
So Clear nice
Dmitry
Commented on 12.July 2011
Thank you! This tutorial is awesome!
Alibaba
Commented on 13.July 2011
I want to create Template for TextBox. How can I aceess RelativeSource TEXT property.
stigma
Commented on 18.July 2011
@Alibaba: If I am understanding you correctly, you would not use RelativeSource to bind to the text property. You would use &quot;{TemplateBinding Text}&quot;. For example:
&lt;TextBlock Text=&quot;{TemplateBinding Text}&quot;/&gt;
Using a TextBox inside a TextBox ControlTemplate, however, I have found to be very unhelpful. Try using: &lt;ScrollViewer x:Name=&quot;PART_ContentHost&quot;/&gt; If you name the ScrollViewer exactly as I have here, the text will be bound to it. No other work required.
Ziad
Commented on 22.August 2011
Life Saver :)
johnson
Commented on 5.September 2011
Machi awesome article...Thanks !!!
Gonzalo
Commented on 20.September 2011
Viva linux!!

Name
E-Mail (optional)
Comment