In this article

11/17/2011

8 minutes to read

In this article

Walkthrough: Customizing the Appearance of a Button by Using a ControlTemplate

You can customize the appearance of a control by giving it a new ControlTemplate. When you create a ControlTemplate, you replace the appearance of an existing control without changing its functionality. This walkthrough creates a ControlTemplate for a Button, but the procedure for creating a custom appearance for any other control would be similar.

In this walkthrough, you create a button that has the following properties.

The button is rectangular with a solid background and a thick black border.

When you move the mouse pointer over the button, the border fades to red.

When you move the mouse pointer away from the button, the border fades to blue, yellow, and then finally to black.

The steps in this walkthrough use Visual Studio, but you can also use Microsoft Expression Blend. Expression Blend provides a graphical user interface for creating control templates. For more information, see Create a Reusable Template for a System Control.

Creating a Silverlight Project in Visual Studio

The first step is to create a Silverlight project.

To create a Silverlight project

Create a new Silverlight Application project named ButtonSkin in Visual Basic or Visual C#. Do not select the Host the Silverlight application in a new Web site check box. For more information, see How to: Create a New Silverlight Project.

Adding the ControlTemplate in a Separate Assembly

In this walkthrough, the ControlTemplate of the Button is created in a separate assembly from the control itself.

To add the ControlTemplate in separate assembly

Add a new Silverlight Class Library project named ButtonControlLibrary to the ButtonSkin solution.

At this point, the control template should look similar to the following XAML. In the next section, you will create your own button structure.

<ResourceDictionary xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:ButtonControlLibrary;assembly=ButtonControlLibrary"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
<Style TargetType="src:MyButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="src:MyButton">
<vsm:VisualStateManager.VisualStateGroups>
<!--Define the states for the common states. The states in a
VisualStateGroup are mutually exclusive to each other.-->
<vsm:VisualStateGroup x:Name="CommonStates">
<!--Define the VisualStates in this VistualStateGroup.-->
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver" />
<vsm:VisualState x:Name="Pressed" />
<vsm:VisualState x:Name="Disabled" />
</vsm:VisualStateGroup>
<!--Define the states for the focus states. The states in a
VisualStateGroup are mutually exclusive to each other.-->
<vsm:VisualStateGroup x:Name="FocusStates">
<!--Define the VisualStates in this VistualStateGroup.-->
<vsm:VisualState x:Name="Focused" />
<vsm:VisualState x:Name="Unfocused" />
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<!--The parts of the button control will be defined here.-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Creating the Visual Structure

The button control created in this section will have the following parts.

Immediately after the </vsm:VisualStateManager.VisualStateGroups> end tag, add the following XAML.

This XAML creates the button background, border and ContentPresenter. It also adds a Rectangle that causes the button to be grayed out when it is disabled.

<!--Create the SolidColorBrush for the Background
as an object elemment and give it a name so
it can be referred to elsewhere in the control template.-->
<Border.Background>
<SolidColorBrush x:Name="BorderBrush" Color="Black"/>
</Border.Background>
<!--Create a border that has a different color by adding smaller grid.
The background of this grid is specified by the button's Background
property.-->
<Grid Background="{TemplateBinding Background}" Margin="4">
<!--Create a Rectangle that indicates that the
Button has focus.-->
<Rectangle Name="FocusVisual"
Visibility="Collapsed" Margin="2"
Stroke="{TemplateBinding Foreground}" StrokeThickness="1"
StrokeDashArray="1.5 1.5"/>
<!--Use a ContentPresenter to display the Content of
the Button.-->
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="4,5,4,4" />
<!--Create a rectangle that causes the button to appear
grayed out when it is disabled.-->
<Rectangle x:Name="DisabledRect"
Fill="#A5FFFFFF"
Opacity="0" IsHitTestVisible="false" />
</Grid>

Immediately after <Style TargetType="src:MyButton">, set the default properties for the button by adding the following XAML.

Defining the Appearance Depending on its State

You use the VisualState objects to specify the appearance of a control when it is in a certain state. A VisualState contains a Storyboard that changes the appearance of the elements that are in the ControlTemplate. In this section, you add XAML for visual states.

To define the appearance depending on its state

In generic.xaml, replace the existing MouseOver state with the following XAML.

This sets the button border to red when the mouse pointer is over the button.

<!--Change the border of the button to red when the
mouse is over the button.-->
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</vsm:VisualState>

Replace the existing Pressed state with the following XAML.

This sets the button border to transparent when the button is in Pressed state.

Specifying the Visual Behavior

Use a VisualTransition to specify the amount of time it takes the control to transition into a particular state. The GeneratedDuration property specifies how long a transition takes. In this section you add XAML for visual transitions.

To specify the visual behavior

In generic.xaml, immediately after the <vsm:VisualStateGroup x:Name="CommonStates"> start tag, add the following Transitions element.

<!--Define the VisualTransitions that can be used when the control transitions between VisualStates that are defined in the VisualStatGroup.-->
<vsm:VisualStateGroup.Transitions>
</vsm:VisualStateGroup.Transitions>

Within the Transitions element, add the following VisualTransition object to specify that the button should take one hundredth of a second to go into the pressed state.

<!--Take one hundredth of a second to transition to the
Pressed state.-->
<vsm:VisualTransition To="Pressed"
GeneratedDuration="0:0:0.01" />

Within the Transitions element, add the following VisualTransition object to specify that the button should take one half of a second to go into the MouseOver state.

<!--Take one half second to trasition to the MouseOver state.-->
<vsm:VisualTransition To="MouseOver"
GeneratedDuration="0:0:0.5" />

Within the Transitions element, add the following VisualTransition object to specify that the button should take one hundredth of a second to go from the Pressed state to the MouseOver state.

<!--Take one hundredth of a second to transition from the
Pressed state to the MouseOver state.-->
<vsm:VisualTransition From="Pressed" To="MouseOver"
GeneratedDuration="0:0:0.01" />

Within the Transitions element, add the following Storyboard to specify that an animation occurs when the control transitions from the MouseOver state to the Normal state.

When the user moves the mouse pointer away from the button, the button's border changes to blue, then to yellow, then to black in 1.5 seconds.

<!--Take one and a half seconds to transition from the
MouseOver state to the Normal state.
Have the SolidColorBrush, BorderBrush, fade to blue,
then to yellow, and then to black in that time.-->
<vsm:VisualTransition From="MouseOver" To="Normal"
GeneratedDuration="0:0:1.5">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="Color"
Storyboard.TargetName="BorderBrush"
FillBehavior="HoldEnd" >
<ColorAnimationUsingKeyFrames.KeyFrames>
<LinearColorKeyFrame Value="Blue"
KeyTime="0:0:0.5" />
<LinearColorKeyFrame Value="Yellow"
KeyTime="0:0:1" />
<LinearColorKeyFrame Value="Black"
KeyTime="0:0:1.5" />
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualTransition>

Build the solution.

Testing the Custom Button

To test the custom button, you need to reference it properly from the application project.

To test the custom button

In the ButtonSkin project, add a reference to the ButtonControlLibrary project.

In MainPage.xaml, add the following namespace mapping to the existing mappings.