Customizing the Appearance of an Existing Control by Using a ControlTemplate
Microsoft Silverlight will reach end of support after October 2021. Learn more.
A ControlTemplate specifies the visual structure and visual behavior of a control. 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. For example, you can make the buttons in your application round rather than the default square shape, but the button will still raise the Click event.
This topic explains the various parts of a ControlTemplate, demonstrates creating a simple ControlTemplate for a Button, and explains how to understand the control contract of a control so you can customize its appearance. Because you create a ControlTemplate in XAML, you can change a control's appearance without writing any code. The examples in this topic show the XAML that is used to customize the appearance of a Button. For the complete example discussed in this topic, see Walkthrough: Customizing the Appearance of a Button by Using a ControlTemplate. You can also use a designer such as Microsoft Expression Blend 2 Service Pack 1 to accomplish the same thing. For more information about using Expression Blend 2 SP1, see Create a Reusable Template for a System Control.
Click the following link to see the ControlTemplate example that is used in this topic.
This topic contains the following sections.
- Prerequisites
- When You Should Create a ControlTemplate
- How to Define the ControlTemplate in XAML
- Changing the Visual Structure of a Control
- Changing the Appearance of a Control Depending on Its State
- Specifying the Behavior of a Control When It Transitions Between States
- Customizing Other Controls by Understanding the Control Contract
- Related Topics
Prerequisites
This topic assumes that you understand creating and using controls and styles as discussed in Getting Started with Controls and the basics of control customization as explained in Control Customization.
Note: |
---|
The concepts discussed in this topic apply to elements that inherit from the Control class, except for the UserControl. You cannot apply a ControlTemplate to a UserControl. |
When You Should Create a ControlTemplate
Controls have many properties, such as Background, Foreground, and FontFamily, that you can set to specify different aspects of the control's appearance, but the changes that you can make by setting these properties are limited. For example, you can set the Foreground property to blue and FontStyle to italic on a CheckBox.
Without the ability to create a new ControlTemplate for controls, all controls in every Silverlight-based application would have the same general appearance, which would limit the ability to create an application with a custom look and feel. By default, every CheckBox has similar characteristics. For example, the content of the CheckBox is always to the right of the selection indicator, and the check mark is always used to indicate that the CheckBox is selected.
You create a ControlTemplate when you want to customize the control's appearance beyond what setting the other properties on the control will do. In the example of the CheckBox, suppose that you want the content of the check box to be above the selection indicator and an X to indicate that the CheckBox is selected. You specify this is the ControlTemplate of the CheckBox.
Click the following link to see a CheckBox that uses a default ControlTemplate and CheckBox that uses a custom ControlTemplate to place the content of the CheckBox above the selection indicator and display an X when the CheckBox is selected.
The ControlTemplate for the CheckBox in this sample is relatively complex, so this topic uses a simpler example of creating a ControlTemplate for a Button.
How to Define the ControlTemplate in XAML
The Template property specifies the ControlTemplate of a control. Like many properties, the Template property can be set in the following ways:
Locally set Template to a ControlTemplate that is defined inline.
Locally set Template to a reference to a ControlTemplate that is defined as a resource.
Set Template and define a ControlTemplate in a Style.
The following example demonstrates setting the Template property locally and defining the ControlTemplate inline.
<Button Content="Button1">
<Button.Template>
<ControlTemplate TargetType="Button">
<!--Define the ControlTemplate here.-->
</ControlTemplate>
</Button.Template>
</Button>
The following example demonstrates defining the ControlTemplate as a resource and setting the Template to a reference to the resource.
<StackPanel>
<StackPanel.Resources>
<ControlTemplate TargetType="Button" x:Key="newTemplate">
<!--Define the ControlTemplate here.-->
</ControlTemplate>
</StackPanel.Resources>
<Button Template="{StaticResource newTemplate}" Content="Button1"/>
</StackPanel>
The following example demonstrates setting the Template property and defining the ControlTemplate in a Style.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button" x:Key="newTemplate">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<!--Define the ControlTemplate here.-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<Button Style="{StaticResource newTemplate}" Content="Button1"/>
</StackPanel>
Although all three of these methods are valid ways to define a ControlTemplate, it is probably most common to see the Template property set in a Style. When you see a ControlTemplate is set in a Style, realize that the style just sets the Template property, just as it does for any other property.
Changing the Visual Structure of a Control
In Silverlight, a control is often a composite FrameworkElement objects. When you create a ControlTemplate, you combine FrameworkElement objects to build a single control. A ControlTemplate must have only one FrameworkElement as its root element. The root element usually contains other FrameworkElement objects. The combination of objects is makes up the control's visual structure.
The following example creates a custom ControlTemplate for the Button. The ControlTemplate creates the visual structure of the Button. This example does not change the button's appearance when you point to it or click it. Changing the button's appearance when it is in a different state is discussed later in this topic.
In this example, the visual structure is made up of the following parts:
A Border called RootElement that serves as the template's root FrameworkElement.
A Grid that is a child of RootElement.
A ContentPresenter that displays the button's content. The ContentPresenter enables any type of object to be displayed.
<ControlTemplate TargetType="Button">
<Border x:Name="RootElement">
<!--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 specificied by the button's Background
property.-->
<Grid Margin="4" Background="{TemplateBinding Background}">
<!--Use a ContentPresenter to display the Content of
the Button.-->
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="4,5,4,4" />
</Grid>
</Border>
</ControlTemplate>
Preserving the Functionality of a Control's Properties by Using TemplateBinding
When you create a new ControlTemplate, you still might want to use the public properties to change the control's appearance. The TemplateBinding markup extension binds a property of an element that is in the ControlTemplate to a public property that is defined by the control. The preceding example uses the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the button. For example, the Border has its Background property set to {TemplateBinding Background}. Because Background is template bound, you can create multiple buttons that use the same ControlTemplate and set the Background to different values on each button. If Background was not template bound in the ControlTemplate, setting the Background of a button would have no impact on the button's appearance.
The Control class defines several properties that can be used by the control template to have an effect on the control when they are set. How the ControlTemplate uses the property depends on the property. The ControlTemplate must use the property in one of the following ways:
An element in the ControlTemplate template binds to the property.
An element in the ControlTemplate inherits the property from a parent FrameworkElement.
The following table lists the visual properties inherited by a control from the Control class. It also indicates whether the default control template of a control uses the inherited property value or if it is template bound.
Property |
Usage method |
---|---|
Background |
Template binding |
BorderThickness |
Template binding |
BorderBrush |
Template binding |
FontFamily |
Property inheritance or template binding |
FontSize |
Property inheritance or template binding |
FontStretch |
Property inheritance or template binding |
FontWeight |
Property inheritance or template binding |
Foreground |
Property inheritance or template binding |
HorizontalContentAlignment |
Template binding |
Padding |
Template binding |
VerticalContentAlignment |
Template binding |
The table above lists only the visual properties inherited from the Control class. Apart from the properties listed above, a control may also inherit the DataContext, Language, and TextDecorations properties from the parent framework element.
Also, if the ContentPresenter is in the ControlTemplate of a ContentControl, the ContentPresenter will automatically bind to the ContentTemplate and Content properties. Likewise, an ItemsPresenter that is in the ControlTemplate of an ItemsControl will automatically bind to the Items and ItemsPresenter properties.
The following example creates two buttons that use the ControlTemplate defined in the preceding example. The example sets the Background, Foreground, and FontSize properties on each button. Setting the Background property has an effect because it is template bound in the ControlTemplate. Even though the Foreground and FontSize properties are not template bound, setting them has an effect because their values are inherited.
<StackPanel>
<Button Style="{StaticResource newTemplate}"
Background="Navy" Foreground="White" FontSize="14"
Content="Button1"/>
<Button Style="{StaticResource newTemplate}"
Background="Purple" Foreground="White" FontSize="14"
Content="Button2" Click="Button_Click"/>
</StackPanel>
Changing the Appearance of a Control Depending on Its State
The difference between a button with its default appearance and the button in the preceding example is that the default button subtly changes when it is in different states. For example, the default button's appearance changes when the button is pressed, or when the mouse pointer is over the button. Although the ControlTemplate does not change the functionality of a control, it does change the control's visual behavior. A visual behavior describes the control appearance when it is in a certain state. To understand the difference between the functionality and visual behavior of a control, consider the button example. The button's functionality is to raise the Click event when it is clicked, but the button's visual behavior is to change its appearance when it is pointed to or pressed.
You use 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. You do not have to write any code to make this occur because the control's logic changes state by using the VisualStateManager. When the control enters the state that is specified by the VisualState.Name property, the storyboard begins. When the control exits the state, the Storyboard stops.
The following example shows the VisualState that changes the appearance of a Button when the mouse pointer is over it. The Name of the VisualState matches the name specified by the TemplateVisualStateAttribute on the Button class. The Storyboard changes the button's border color by changing the color of the BorderBrush. If you refer to the ControlTemplate example at the beginning of this topic, you will recall that BorderBrush is the name of the SolidColorBrush that is assigned to the Background of the Border.
<!--Change the border of the button to red when the
mouse is over the button.-->
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</VisualState>
The control is responsible for defining the states as part of its control contract, which is discussed in detail in Customizing Other Controls by Understanding the Control Contract later in this topic. The states of a control are specified by the TemplateVisualStateAttribute, which is placed on the control's class definition. A TemplateVisualStateAttribute specifies the name of the state and the name of the state group that the state belongs to. The following example shows the states that are specified for the Button.
<TemplateVisualStateAttribute(Name:="Pressed", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Focused", GroupName:="FocusStates")> _
<TemplateVisualStateAttribute(Name:="Normal", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="MouseOver", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Disabled", GroupName:="CommonStates")> _
<TemplateVisualStateAttribute(Name:="Unfocused", GroupName:="FocusStates")> _
Public Class Button
Inherits ButtonBase
End Class
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
public class Button : ButtonBase
{
}
The TemplateVisualStateAttribute.GroupName property specifies which group a state belongs to. In the preceding example, the Button defines two state groups: the CommonStates group contains the Normal, MouseOver, Pressed, and Disabled states. The FocusStates group contains the Focused and Unfocused states. States in the same state group are mutually exclusive. The control is always in exactly one state per group. For example, a Button can have focus even when the mouse pointer is not over it, so a Button in the Focused state can be in the MouseOver, Pressed, or Normal state.
You add VisualState objects to VisualStateGroup objects. You add VisualStateGroup objects to the VisualStateManager.VisualStateGroups attached property, which you set on the root FrameworkElement of the ControlTemplate. The following example defines the VisualState objects for the Normal, MouseOver, and Pressed states, which are all in the CommonStates group. The Disabled state and the states in the FocusStates group are omitted to keep the example short, but they are included in the entire example in Walkthrough: Customizing the Appearance of a Button by Using a ControlTemplate.
<ControlTemplate TargetType="Button">
<Border x:Name="RootElement">
<VisualStateManager.VisualStateGroups>
<!--Define the states for the common states.
The states in the VisualStateGroup are mutually exclusive to
each other.-->
<VisualStateGroup x:Name="CommonStates">
<!--The Normal state is the state the button is in
when it is not in another state from this VisualStateGroup.-->
<VisualState x:Name="Normal" />
<!--Change the SolidColorBrush, BorderBrush, to red when the
mouse is over the button.-->
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</VisualState>
<!--Change the SolidColorBrush, BorderBrush, to Transparent when the
button is pressed.-->
<VisualState x:Name="Pressed">
<Storyboard >
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Transparent"/>
</Storyboard>
</VisualState>
<!--The Disabled state is omitted for brevity.-->
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border.Background>
<SolidColorBrush x:Name="BorderBrush" Color="Black"/>
</Border.Background>
<Grid Background="{TemplateBinding Background}" Margin="4">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="4,5,4,4" />
</Grid>
</Border>
</ControlTemplate>
Specifying the Behavior of a Control When It Transitions Between States
If you run the preceding sample, you will notice that the appearance of a button changes when you point to it. The appearance of the button also changes when you click it, but unless you keep the button pressed for a full second, you do not see the effect. By default, an animation takes one second to occur. Because users are likely to click and release a button in much less time, the visual feedback will not be effective if you leave the ControlTemplate in its default state.
You can specify the amount of time that it takes an animation to occur to smoothly transition a control from one state to another by adding VisualTransition objects to the ControlTemplate. When you create a VisualTransition, you specify one or more of the following:
The time it takes for a transition between states to occur.
Additional changes in the control's appearance that occur at the time of the transition.
Which states the VisualTransition is applied to.
Specifying the Duration of a Transition
You can specify how long a transition takes by setting the GeneratedDuration property. The preceding example has a VisualState that specifies that the button's border becomes transparent when the button is pressed, but the animation takes too long to be noticeable if the button is quickly pressed and released. You can use a VisualTransition to specify the amount of time it takes the control to transition into the pressed state. The following example specifies that the control takes one hundredth of a second to go into the pressed state.
<!--Take one hundredth of a second to transition to the
Pressed state.-->
<VisualTransition To="Pressed"
GeneratedDuration="0:0:0.01" />
Specifying Changes to the Control's Appearance During a Transition
The VisualTransition contains a Storyboard that begins when the control transitions between states. For example, you can specify that a certain animation occurs when the control transitions from the MouseOver state to the Normal State. The following example creates a VisualTransition that specifies that 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.-->
<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>
</VisualTransition>
Specifying When a VisualTransition Is Applied
In the preceding example, the VisualTransition is applied when the control goes from the MouseOver state to the Normal state; in the example before that, the VisualTransition is applied when the control goes into the Pressed state. A VisualTransition can be restricted to apply to only certain states, or it can be applied any time the control transitions between states. You restrict when a VisualTransition is applied by setting the To and From properties. The following table describes the levels of restriction from most restrictive to least restrictive.
Type of restriction |
Value of From |
Value of To |
---|---|---|
From a specified state to another specified state |
The name of a VisualState |
The name of a VisualState |
From any state to a specified state |
Not set |
The name of a VisualState |
From a specified state to any state |
The name of a VisualState |
Not set |
From any state to any other state |
Not set |
Not set |
You can have multiple VisualTransition objects in a VisualStateGroup that refer to the same state, but they will be used in the order that the table above specifies. In the following example, there are two VisualTransition objects. When the control transitions from the Pressed state to the MouseOver state, the VisualTransition that has both From and To set is used. When the control transitions from a state that is not Pressed to the MouseOver state, the other state is used.
<!--Take one half second to trasition to the MouseOver state.-->
<VisualTransition To="MouseOver"
GeneratedDuration="0:0:0.5" />
<!--Take one hundredth of a second to transition from the
Pressed state to the MouseOver state.-->
<VisualTransition From="Pressed" To="MouseOver"
GeneratedDuration="0:0:0.01" />
The VisualStateGroup has a Transitions property that contains the VisualTransition objects that apply to the VisualState objects in the VisualStateGroup. As the ControlTemplate author, you are free to include any VisualTransition you want. However, if the To and From properties are set to state names that are not in the VisualStateGroup, the VisualTransition is ignored.
The following example shows the VisualStateGroup for the CommonStates. The example defines a VisualTransition for each of the button's following transitions.
To the Pressed state.
To the MouseOver state.
From the Pressed state to the MouseOver state.
From the MouseOver state to the Normal state.
<VisualStateGroup x:Name="CommonStates">
<!--Define the VisualTransitions that can be used when the control
transitions between VisualStates that are defined in the
VisualStatGroup.-->
<VisualStateGroup.Transitions>
<!--Take one hundredth of a second to transition to the
Pressed state.-->
<VisualTransition To="Pressed"
GeneratedDuration="0:0:0.01" />
<!--Take one half second to trasition to the MouseOver state.-->
<VisualTransition To="MouseOver"
GeneratedDuration="0:0:0.5" />
<!--Take one hundredth of a second to transition from the
Pressed state to the MouseOver state.-->
<VisualTransition From="Pressed" To="MouseOver"
GeneratedDuration="0:0:0.01" />
<!--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.-->
<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>
</VisualTransition>
</VisualStateGroup.Transitions>
<!--The remainder of the VisualStateGroup is the
same as the previous example.-->
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Red" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard >
<ColorAnimation Storyboard.TargetName="BorderBrush"
Storyboard.TargetProperty="Color" To="Transparent"/>
</Storyboard>
</VisualState>
<!--The Disabled state is omitted for brevity.-->
</VisualStateGroup>
Customizing Other Controls by Understanding the Control Contract
A control that uses a ControlTemplate to specify its visual structure (by using FrameworkElement objects) and visual behavior (by using VisualState objects) uses the parts control model. Many of the controls that ship with Silverlight and third-party controls use this model. The parts that a ControlTemplate author needs to be aware of are communicated through the control contract. When you understand the parts of a control contract, you can customize the appearance of any control that uses the parts control model.
A control contract has three elements:
The visual elements that the control's logic uses.
The states of the control and the group each state belongs to.
The public properties that visually affect the control.
Visual Elements in the Control Contract
Sometimes a control's logic interacts with a FrameworkElement that is in the ControlTemplate. For example, the control might handle an event of one of its elements. When a control expects to find a particular FrameworkElement in the ControlTemplate, it must convey that information to the ControlTemplate author. The control uses the TemplatePartAttribute to convey the type of element that is expected, and what the name of the element should be. The Button does not have FrameworkElement parts in its control contract, but other controls, such as the ComboBox, do.
The following example shows the TemplatePartAttribute objects that are specified on the ComboBox class. The logic of ComboBox expects to find a Popup named Popup and a ContentPresenter named ContentPresenter in its ControlTemplate.
<TemplatePartAttribute(Name:="ContentPresenter", Type:=GetType(ContentPresenter))> _
<TemplatePartAttribute(Name:="Popup", Type:=GetType(Popup))> _
Public Class ComboBox
Inherits ItemsControl
End Class
[TemplatePartAttribute(Name = "ContentPresenter", Type = typeof(ContentPresenter))]
[TemplatePartAttribute(Name = "Popup", Type = typeof(Popup))]
public class ComboBox : ItemsControl
{
}
The following example shows a simplified ControlTemplate for the ComboBox that includes the elements that are specified by the TemplatePartAttribute objects on the ComboBox class.
<ControlTemplate TargetType="ComboBox">
<Grid>
<Border x:Name="ContentPresenterBorder">
<Grid>
<ToggleButton x:Name="DropDownToggle"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Margin="-1" HorizontalContentAlignment="Right">
<Path x:Name="BtnArrow" Height="4" Width="8"
Stretch="Uniform" Margin="0,0,6,0" Fill="Black"
Data="F1 M 300,-190L 310,-190L 305,-183L 301,-190 Z " />
</ToggleButton>
<ContentPresenter x:Name="ContentPresenter" Margin="6,2,25,2">
<TextBlock Text=" " />
</ContentPresenter>
</Grid>
</Border>
<Popup x:Name="Popup">
<Border x:Name="PopupBorder"
HorizontalAlignment="Stretch" Height="Auto"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="Black" Background="White" CornerRadius="3">
<ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
States in the Control Contract
The states of a control are also a part of the control contract. The example of creating a ControlTemplate for a Button shows how to specify the appearance of a Button depending on its states. As described in Changing the Appearance of a Control Depending on Its State earlier in this topic, the states of a control are specified by the TemplateVisualStateAttribute. You create a VisualState for each specified state and put all VisualState objects that share a GroupName in a VisualStateGroup.
Properties in the Control Contract
The public properties that visually affect the control are also included in the control contract. You can set these properties to change the appearance of the control without creating a new ControlTemplate. You can also use the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the Button.
For controls that ship with Silverlight 5, you can find the visual element and states that are included in the control contract by looking at the control's reference topic. For example, the syntax section on the ComboBox class reference shows the TemplatePartAttribute and the TemplateVisualStateAttribute that the ComboBox specifies. Although your application should run without throwing an exception if you do not include an expected FrameworkElement or VisualState, the control may not behave as expected. Any public property that affects the control visually is also a part of the control contract.
The following example summarizes the control contract for the button.
<TemplateVisualState(Name:="Normal", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Pressed", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Disabled", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates")> _
<TemplateVisualState(Name:="Focused", GroupName:="FocusStates")> _
Public Class Button
Inherits ButtonBase
Public Shared ReadOnly BackgroundProperty As DependencyProperty
Public Shared ReadOnly BorderBrushProperty As DependencyProperty
Public Shared ReadOnly BorderThicknessProperty As DependencyProperty
Public Shared ReadOnly ContentProperty As DependencyProperty
Public Shared ReadOnly ContentTemplateProperty As DependencyProperty
Public Shared ReadOnly FontFamilyProperty As DependencyProperty
Public Shared ReadOnly FontSizeProperty As DependencyProperty
Public Shared ReadOnly FontStretchProperty As DependencyProperty
Public Shared ReadOnly FontStyleProperty As DependencyProperty
Public Shared ReadOnly FontWeightProperty As DependencyProperty
Public Shared ReadOnly ForegroundProperty As DependencyProperty
Public Shared ReadOnly HorizontalContentAlignmentProperty As DependencyProperty
Public Shared ReadOnly PaddingProperty As DependencyProperty
Public Shared ReadOnly TextAlignmentProperty As DependencyProperty
Public Shared ReadOnly TextDecorationsProperty As DependencyProperty
Public Shared ReadOnly TextWrappingProperty As DependencyProperty
Public Shared ReadOnly VerticalContentAlignmentProperty As DependencyProperty
Public Background As Brush
Public BorderBrush As Brush
Public BorderThickness As Thickness
Public Content As Object
Public ContentTemplate As DataTemplate
Public FontFamily As FontFamily
Public FontSize As Double
Public FontStretch As FontStretch
Public FontStyle As FontStyle
Public FontWeight As FontWeight
Public Foreground As Brush
Public HorizontalContentAlignment As HorizontalAlignment
Public Padding As Thickness
Public TextAlignment As TextAlignment
Public TextDecorations As TextDecorationCollection
Public TextWrapping As TextWrapping
Public VerticalContentAlignment As VerticalAlignment
End Class
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
public class Button : ButtonBase
{
public static readonly DependencyProperty BackgroundProperty;
public static readonly DependencyProperty BorderBrushProperty;
public static readonly DependencyProperty BorderThicknessProperty;
public static readonly DependencyProperty ContentProperty;
public static readonly DependencyProperty ContentTemplateProperty;
public static readonly DependencyProperty FontFamilyProperty;
public static readonly DependencyProperty FontSizeProperty;
public static readonly DependencyProperty FontStretchProperty;
public static readonly DependencyProperty FontStyleProperty;
public static readonly DependencyProperty FontWeightProperty;
public static readonly DependencyProperty ForegroundProperty;
public static readonly DependencyProperty HorizontalContentAlignmentProperty;
public static readonly DependencyProperty PaddingProperty;
public static readonly DependencyProperty TextAlignmentProperty;
public static readonly DependencyProperty TextDecorationsProperty;
public static readonly DependencyProperty TextWrappingProperty;
public static readonly DependencyProperty VerticalContentAlignmentProperty;
public Brush Background { get; set; }
public Brush BorderBrush { get; set; }
public Thickness BorderThickness { get; set; }
public object Content { get; set; }
public DataTemplate ContentTemplate { get; set; }
public FontFamily FontFamily { get; set; }
public double FontSize { get; set; }
public FontStretch FontStretch { get; set; }
public FontStyle FontStyle { get; set; }
public FontWeight FontWeight { get; set; }
public Brush Foreground { get; set; }
public HorizontalAlignment HorizontalContentAlignment { get; set; }
public Thickness Padding { get; set; }
public TextAlignment TextAlignment { get; set; }
public TextDecorationCollection TextDecorations { get; set; }
public TextWrapping TextWrapping { get; set; }
public VerticalAlignment VerticalContentAlignment { get; set; }
}
When creating a ControlTemplate, it is often easiest to begin with an existing ControlTemplate and making changes to it. You can do one of the following to change an existing ControlTemplate:
Use a designer such as Microsoft Expression Blend, which provides a graphical user interface for creating control templates. For more information, see Create a Reusable Template for a System Control.
Get the default ControlTemplate and edit it. To see the default templates for controls that ship with Silverlight, see Control Styles and Templates.
To successfully create a ControlTemplate, you must understand the control's control contract. When you understand the parts of a control contract, you can create a new ControlTemplate for existing controls and create an application that has a unique look and feel.
See Also