16
2006
ControlTemplates in XAML
XAML has this great concept of look-less controls. When we see a normal Win32 control like say a checkbox, we always assume that it will be a square box along with some text written to the left of it. Taking an example from our old friend WordPad, we would always expect a checkbox to look like

Pretty boring, if you would ask a kid (or even a teenager!). Even though it makes the control much more usable (which is a very important thing BTW), it doesn’t look cool. So how does WPF help us here?
For starters, when you define a control, WPF doesn’t force to you to define the look of the control along with the functionality. Here comes the concept of a look-less control; a control whose behaviour is defined but whose look is not defined. For instance, we might define the behavior of the check box (it has a bool or a bool? property called IsChecked, it has a check mark to the left of the content, etc…
but leave it to the author to define the look for it. So we might have something like
|
|
Checked Checkbox |
|
|
Unchecked Checkbox |
How to go about doing this? This is all done by redefining the ControlTemplate for the checkbox. ControlTemplate is basically what it says, it is a Template for the Control and decides how the control will look like. To achieve such a look we define the Style of the Checkbox as
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}"> <Setter Property="SnapsToDevicePixels" Value="true"/> <Setter Property="OverridesDefaultStyle" Value="true"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type CheckBox}"> <WrapPanel Orientation="Horizontal"> <Border x:Name="Border" CornerRadius="0” > <Image Name="CheckMark" Height="{Binding ElementName=MyContent, Path=ActualHeight}" Source="happy.gif"> <Image.BitmapEffect> <OuterGlowBitmapEffect GlowColor="Blue" GlowSize="2” Noise=".1” Opacity="0.8"/> </Image.BitmapEffect> </Image> </Border> <ContentPresenter Margin="4,0,0,0" Name="MyContent" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True"/> </WrapPanel> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="{x:Null}"> <Setter TargetName="CheckMark" Property="Source" Value="unsure.gif" /> <Setter Property="BitmapEffect" TargetName="CheckMark"> <Setter.Value> <OuterGlowBitmapEffect GlowColor="Black" GlowSize="2" Noise=".1" Opacity="0.8" /> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsChecked" Value="false"> <Setter TargetName="CheckMark" Property="Source" Value="sad.gif" /> <Setter Property="BitmapEffect" TargetName="CheckMark" Value="{x:Null}"/> </Trigger> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="BitmapEffect" TargetName="CheckMark"> <Setter.Value> <OuterGlowBitmapEffect GlowColor="Red" GlowSize="2" Noise=".1" Opacity="0.8" /> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsPressed" Value="true"> <Setter Property="BitmapEffect" TargetName="CheckMark"> <Setter.Value> <OuterGlowBitmapEffect GlowColor="Yellow" GlowSize="2" Noise=".1" Opacity="0.8" /> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" /> <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" /> <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
Let’s dissect this monster to see how it works ![]()
The first line
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
means that this is a Style being defined for Type CheckBox in the namespace referred to by x which is http://schemas.microsoft.com/winfx/2006/xaml in my case.
Moving on, the core part of the Style is in defining the ControlTemplarte.
<ControlTemplate TargetType="{x:Type CheckBox}">
Note that I could have defined the ControlTemplate for the CheckBox using CheckBox.ControlTemplate but have chosen to implement it using a Style as it is quite common to do so.
It is in this ControlTemplate that I define the look of the CheckBox. Here I say that it should be a WrapPanel which should contain a Border which has an Image and a ContentPresenter in it. You can read more about the ContentPresenter in MSDN, it is just a UIElement which can contain and display any other object. The Image has a binding to the Height of the ContentPresenter so that it resizes automatically to the Height of the content, else you might have a case when you have text with FontSize 36 points but you checkmark is just 10 pixels high. That’s it! That’s the definition of our customized CheckBox; could it be any easier?
I added some Triggers to change the Image in the CheckBox depending on its state. I have added an image when IsChecked is null to account for a Tri State CheckBox. I also added some BitmapEffects for a Glow (just to make it more pretty!)
Go through the code, it isn’t very hard to understand or comprehend. Now whenever you wish your CheckBox to use this style, simply use it as
<CheckBox Margin="8” Style="myCheckBoxStyle"> <TextBlock FontSize="20">Happy or Sad?</TextBlock> </CheckBox>
If you find this article useful, do comment and let me know


Incredibly nice article i have to say and no i am not just saying it i mean it !!!
Nice article, but I have to say thats quite a bit of code/markup just to make an image box that changes appearance when you click on it
Unfortunately that is the part of the game. WPF does not allow (yet!) one to edit specific parts of the ControlTemplate; so even for a minor change one has to redefine the complete ControlTemplate. This might make some sense as when you are mdifying only a part of the ControlTemplate, you might change something that is closely coupled with the rest of the template; that’s my guess why this hasn’t been done.
On the other hand, things are much easier if these properties are exposed as Styles. We could just extend from the Style and overwrite only those properties that interest us. Though this severely limits us to controlling only the properties that are exposed as Dependency Properties on the control.
Just what I was looking for, thanks!