Silverlight 2 - Creating a Play/Pause button using a ControlTemplate
A Button is one of the most common elements used in an interactive application. In Silverlight 2, it is possible to specify nearly any control’s appearance by using a ControlTemplate. The control’s template can be defined within the control’s <ControlTemplate/> inner property, or it can be built as a resource at the page or application level. We can reference these resources in the control's Style or ControlTemplate property (ControlTemplate can be a child of a Style, making it possible to add additional Setters to that Style).
In this sample, we'll create a Play/Pause button that can be used in a media player. We'll end up with a ControlTemplate in the App.xaml that can be reused for several media controls (i.e. Stop, Forward, Backward, etc.) by setting their Template property.
Creating a simple ControlTemplate
Using Blend, I can generate some of markup to get started. First, create a Button control in Blend within the Silverlight Object structure:

<Button x:Name="PlayPause" />
To create an empty ControlTemplate for this button, right-click the button in the Object Viewer, and create an blank template:

This will modify the Button Xaml to reference the new resource,
<Button x:Name="PlayPause" Template="{StaticResource MediaControl}"/>
and will generate the following in the App.xaml resources, based on the Button control's pre-defined TemplateVisualStates:
<ControlTemplate x:Key="MediaControl" TargetType="Button">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Pressed"/>
<vsm:VisualState x:Name="Disabled"/>
<vsm:VisualState x:Name="Normal"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
We can see Button's pre-defined visual states by looking up the class' custom attributes (http://msdn.microsoft.com/en-us/library/system.windows.controls.button(VS.95).aspx):
[TemplateVisualStateAttribute(Name = "Unfocused", GroupName = "FocusStates")][TemplateVisualStateAttribute(Name = "MouseOver", GroupName = "CommonStates")][TemplateVisualStateAttribute(Name = "Pressed", GroupName = "CommonStates")][TemplateVisualStateAttribute(Name = "Focused", GroupName = "FocusStates")][TemplateVisualStateAttribute(Name = "Disabled", GroupName = "CommonStates")][TemplateVisualStateAttribute(Name = "Normal", GroupName = "CommonStates")]public class Button : ButtonBase
We can either modify the Xaml by hand or use the States Viewer in the June release of Blend, either way, we'll need to add Storyboards for any desired visual state:

I'll first create the base template style, which is a circular button without the play or pause icons. The updated template Xaml looks like this:
<ControlTemplate x:Key="MediaControl" TargetType="Button">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Pressed"/>
<vsm:VisualState x:Name="Disabled"/>
<vsm:VisualState x:Name="Normal"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Path Stretch="Fill" Fill="#FF5575AF" Data="F1 M 37.323,458.684C 37.323,466.181 31.246,472.258 23.75,472.258C 16.253,472.258 10.176,466.181 10.176,458.684C 10.176,451.187 16.253,445.11 23.75,445.11C 31.246,445.11 37.323,451.187 37.323,458.684 Z " Height="27.1480102539063" Width="27.1470031738281" Canvas.Top="0.371"/>
<Path x:Name="Fade" Stretch="Fill" Data="F1 M 38.323,457.684C 38.323,465.181 32.246,471.258 24.75,471.258C 17.253,471.258 11.176,465.181 11.176,457.684C 11.176,450.187 17.253,444.11 24.75,444.11C 32.246,444.11 38.323,450.187 38.323,457.684 Z " Height="27.1480102539063" Width="27.1470031738281" Canvas.Left="0.913" Canvas.Top="-0.625">
<Path.Fill>
<RadialGradientBrush RadiusX="0.895406" RadiusY="0.895374" Center="0.5,0.999993" GradientOrigin="0.5,0.999993">
<RadialGradientBrush.RelativeTransform>
<TransformGroup/>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FF668ECC" Offset="1"/>
</RadialGradientBrush>
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>

Now I want to add a MouseOver state, so I'll change the following VisualState to create a glow effect on the button:
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="Fade" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="#FF98BFFB"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
Now my button is glowing nicely on mouseover, and I haven't had to write any C# yet!

Adding Button Content (Play and Pause icons)
The play and pause icons will need to exist within the control’s Content in order for us to access them in the code-behind. There is currently no support for accessing items within the ControlTemplate, but something tells me this will be supported in the future. One downside to separating the icons from the ControlTemplate is that we cannot include visual states for the icons… There are worse things in life. The positive side is that we can specify where content shows up in the template by adding a ContentPresenter to the template:
<ControlTemplate x:Key="MediaControl" TargetType="Button">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Pressed"/>
<vsm:VisualState x:Name="Disabled"/>
<vsm:VisualState x:Name="Normal"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Path Stretch="Fill" Fill="#FF5575AF" Data="F1 M 37.323,458.684C 37.323,466.181 31.246,472.258 23.75,472.258C 16.253,472.258 10.176,466.181 10.176,458.684C 10.176,451.187 16.253,445.11 23.75,445.11C 31.246,445.11 37.323,451.187 37.323,458.684 Z " Height="27.1480102539063" Width="27.1470031738281" Canvas.Top="0.371"/>
<Path x:Name="Fade" Stretch="Fill" Data="F1 M 38.323,457.684C 38.323,465.181 32.246,471.258 24.75,471.258C 17.253,471.258 11.176,465.181 11.176,457.684C 11.176,450.187 17.253,444.11 24.75,444.11C 32.246,444.11 38.323,450.187 38.323,457.684 Z " Height="27.1480102539063" Width="27.1470031738281" Canvas.Left="0.913" Canvas.Top="-0.625">
<Path.Fill>
<RadialGradientBrush RadiusX="0.895406" RadiusY="0.895374" Center="0.5,0.999993" GradientOrigin="0.5,0.999993">
<RadialGradientBrush.RelativeTransform>
<TransformGroup/>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FF668ECC" Offset="1"/>
</RadialGradientBrush>
</Path.Fill>
</Path>
<ContentPresenter/>
</Grid>
</ControlTemplate>
We could add another element below the ContentPresenter, allowing for the possibility of a gradient over the top of our icons, which can be edited in the visual states.
To add the play and pause icons, we'll simply add Xaml to be a child-node of the Button:
<Button x:Name="PlayPause" Template="{StaticResource MediaControl}" Canvas.Left="5" Canvas.Top="5" Click="PlayPauseButton_Click">
<Canvas Height="9.353" Width="8.68">
<Path Height="9.353" x:Name="PlayIcon" Width="8.68" Fill="#FF2C5E90" Stretch="Fill" Data="M15.639187,16.184645 L15.627616,24.492212 L23.324333,20.374496 z"/>
<StackPanel Height="9.353" Width="8.68" x:Name="PauseIcon" Orientation="Horizontal">
<Rectangle Height="9.353" Width="2.18" Fill="#FF2C5E90" Margin="0,0,1,0"/>
<Rectangle Height="9.353" Width="2.18" Fill="#FF2C5E90" Margin="2,0,0,0"/>
</StackPanel>
</Canvas>
</Button>

All of this templating work sets us up nicely to write some simple logic for the Button's Click handler:
private void PlayPauseButton_Click(object sender, RoutedEventArgs e)
{
if (VideoPlayer.CurrentState == MediaElementState.Playing)
{
VideoPlayer.Pause();
PauseIcon.Visibility = Visibility.Collapsed;
PlayIcon.Visibility = Visibility.Visible;
}
else
{
VideoPlayer.Pause();
PlayIcon.Visibility = Visibility.Collapsed;
PauseIcon.Visibility = Visibility.Visible;
}
}