
Introduction
This is the second article in the WPFSpark series. WPFSpark is an Open Source project in CodePlex containing a library of user controls which can be used by the developer community. I was planning to write this article a few weeks ago, but I was preoccupied with creating a few more exciting controls for the WPFSpark library. I will be describing these controls in my forthcoming articles.
In this article, I describe in detail about the second control in this library which I have developed. It is called the ToggleSwitch control and it derives from ToggleButton and provides a rich user experience. It supports only two states: True or False.

The previous article in the WPFSpark series can be accessed here:
- WPFSpark: 1 of n: SprocketControl
Background
ToggleButton
System.Windows.Controls.Primitives.ToggleButton is a base class for controls that can switch states, such as CheckBox. It supports three states: True, False, and Null.

FluidMoveBehavior
Before delving into the details of the ToggleSwitch, one more WPF feature (which plays an important role in the ToggleSwitch control) needs mention - FluidMoveBehavior. FluidMoveBehavior is an Expression Blend feature which allows you to animate a change in the position of an element. The animation looks very realistic as it allows the use of EasingFunctions. Here are a few links which describe the FluidMoveBehavior in much more detail:
ToggleSwitch Control Demystified
Simple ToggleSwitch
The first version of the ToggleSwitch control which I created was the Simple ToggleSwitch control. In order to create it, I defined a custom template for the ToggleButton, which had a Grid consisting of two columns and a single row.

The first column (Column 0) contained a TextBlock which would define the text for the Checked state. Similarly, the second column (Column 1) contained a TextBlock which would define the text for the Unchecked state.

Additionally, the template also contained a Border depicting the Thumb of the ToggleSwitch. The location of the Thumb, in the grid, would be either the first or the second column depending upon whether the ToggleSwitch is in the Checked or Unchecked state.


Adding the FluidMoveBehavior to the Grid will ensure that whenever the state of the ToggleSwitch changes, the movement of the Thumb from one column to the other will be animated and not instantaneous. (You should add references of Microsoft.Expression.Interactions.dll and System.Windows.Interactivity.dll to your project to get the FluidMoveBehaviour.)
Here is the control template for the Simple ToggleSwitch:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions">
<Style x:Key="ToggleSwitchStyle"
TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ControlTemplate.Resources>
<Storyboard x:Key="Timeline1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Timeline2">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid MinWidth="120"
MinHeight="40"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Background="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<i:Interaction.Behaviors>
<ei:FluidMoveBehavior AppliesTo="Children"
Duration="0:0:0.25">
<ei:FluidMoveBehavior.EaseX>
<SineEase EasingMode="EaseIn" />
</ei:FluidMoveBehavior.EaseX>
</ei:FluidMoveBehavior>
</i:Interaction.Behaviors>
<Border Grid.ColumnSpan="2"
BorderBrush="LightGray"
Background="Transparent"
CornerRadius="6"
BorderThickness="1"></Border>
<TextBlock x:Name="OffText"
Grid.Column="0"
HorizontalAlignment="Center"
Text="Debug"
FontFamily="/CvisBuilder;Component/Resources/Font/#Segoe WP"
FontWeight="Light"
VerticalAlignment="Center"
Foreground="LawnGreen"
FontSize="{TemplateBinding FontSize}"></TextBlock>
<TextBlock x:Name="OnText"
Grid.Column="1"
HorizontalAlignment="Center"
FontFamily="/CvisBuilder;Component/Resources/Font/#Segoe WP"
FontWeight="Light"
Text="Release"
VerticalAlignment="Center"
Foreground="LawnGreen"
FontSize="{TemplateBinding FontSize}"></TextBlock>
<Border Name="Thumb"
Grid.Column="0"
BorderBrush="White"
BorderThickness="1"
Margin="3"
CornerRadius="4"
Background="#222222">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.507*" />
<RowDefinition Height="0.493*" />
</Grid.RowDefinitions>
<Border Opacity="0"
HorizontalAlignment="Stretch"
x:Name="Glow"
Width="Auto"
Grid.RowSpan="2"
CornerRadius="2">
<Border.Background>
<RadialGradientBrush>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.702"
ScaleY="2.743" />
<SkewTransform AngleX="0"
AngleY="0" />
<RotateTransform Angle="0" />
<TranslateTransform X="-0.368"
Y="-0.152" />
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="LawnGreen"
Offset="0" />
<GradientStop Color="#44006400"
Offset="0.75" />
</RadialGradientBrush>
</Border.Background>
</Border>
<Border HorizontalAlignment="Stretch"
Margin="0,0,0,0"
x:Name="shine"
Width="Auto"
CornerRadius="2,2,0,0">
<Border.Background>
<LinearGradientBrush EndPoint="0.494,0.889"
StartPoint="0.494,0.028">
<GradientStop Color="#99FFFFFF"
Offset="0" />
<GradientStop Color="#33FFFFFF"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="true">
<Setter Property="Grid.Column"
TargetName="Thumb"
Value="1" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Opacity"
Value="0.4" />
<Setter TargetName="OffText"
Property="Foreground"
Value="LightGray"></Setter>
<Setter TargetName="OnText"
Property="Foreground"
Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsPressed"
Value="True">
<Setter Property="Opacity"
TargetName="shine"
Value="0.6" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard
Storyboard="{StaticResource Timeline1}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard x:Name="Timeline2_BeginStoryboard"
Storyboard="{StaticResource Timeline2}" />
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Sophisticated ToggleSwitch
Though I was happy with the accomplishment of the Simple ToggleSwitch creation, I was far from being satisfied. I wanted to make the ToggleSwitch appear more realistic by making the TextBlocks (used for displaying the two states of the ToggleSwitch) appear along with the Thumb. I also wanted to make the ToggleSwitch control easily skinnable by modifying a few properties.
To accomplish this, the first requirement was a WPF Grid with rounded corners. Since the Grid does not have the CornerRadius property, the other option I had was to encapsulate the Grid within a Border and set the ClipToBounds property of the Border to true. Then I found out that Border (and all decorators) do not perform the clipping even though ClipToBounds is set to true.
For this purpose, I wrote the ClipBorder class. It also allows the user to specify different corner radius for each of the corners of the border. (For more details, check out my article in my blog - ClipBorder: A WPF Border that clips.)
Now the ClipBorder will encapsulate the Grid (named PART_RootGrid) that will be used to position the content of the ToggleSwitch based on its state. This Grid has three columns (Left, Center, and Right). The width of each column is dynamically calculated based on the width of the Thumb.

The Content of the ToggleSwitch is placed in another Grid (named PART_ContentGrid). This Grid contains five columns (Left, CenterLeft, Center, CenterRight, and Right).

The ContentGrid contains the following:
CheckedBorder - This defines the background that is displayed in the Checked state of the ToggleSwitch control. It occupies the Left and CentreLeft columns.
CheckedTextBlock - This contains the text that is displayed in the Checked state. It occupies the Left column.
Thumb - This contains the thumb of the ToggleSwitch control. It occupies the CenterLeft, Center, and CenterRight columns.
UncheckedBorder - This defines the background that is displayed in the Unchecked state of the ToggleSwitch control. It occupies the CentreRight and Right columns.
UncheckedTextBlock - This contains the text that is displayed in the Unchecked state. It occupies the Right column.
The Thumb contains another Grid which contains a Border which provides a shine to the Thumb.
The image below shows the outermost ClipBorder and the ContentGrid in details.

Here is the Exploded 3D view of a ToggleSwitch control obtained using a wonderful tool called Snoop.

The ContentGrid has a larger width than the RootGrid, but since both are encapsulated within a ClipBorder, the portion outside the ClipBorder is clipped. Based on the state of the ToggleSwitch (True or False) and the size of the thumb, the column within the RootGrid where the ContentGrid has to be placed is calculated.
The ThumbWidth dependency property of the ToggleSwitch control defines the width of the Thumb as a percentage of the Total Width of the ToggleSwitch control. It can have values ranging from 10 to 90 (inclusive). Based on the ThumbWidth, the width of each of the columns of the RootGrid and the ContentGrid and the margin of the ContentGrid are calculated. The code below shows the calculation:
private void CalculateLayout()
{
if ((rootGrid == null) || (contentGrid == null))
return;
double thumbPercentage = ThumbWidth / 100.0;
double contentPercentage = 1 - thumbPercentage;
if (thumbPercentage <= 0.5)
{
rootGrid.ColumnDefinitions[0].Width =
new GridLength(thumbPercentage, GridUnitType.Star);
rootGrid.ColumnDefinitions[1].Width =
new GridLength(1.0 - (2 * thumbPercentage), GridUnitType.Star);
rootGrid.ColumnDefinitions[2].Width =
new GridLength(thumbPercentage, GridUnitType.Star);
TargetColumnInternal = 2;
Grid.SetColumnSpan(contentBorder, 1);
}
else
{
rootGrid.ColumnDefinitions[0].Width =
new GridLength(contentPercentage, GridUnitType.Star);
rootGrid.ColumnDefinitions[1].Width =
new GridLength(1.0 - (2 * contentPercentage), GridUnitType.Star);
rootGrid.ColumnDefinitions[2].Width =
new GridLength(contentPercentage, GridUnitType.Star);
TargetColumnInternal = 1;
Grid.SetColumnSpan(contentBorder, 2);
}
double leftRight = (1 - thumbPercentage) / (2 - thumbPercentage);
double centerLeftRight = 0.485 - leftRight;
double center = 0.03;
contentGrid.ColumnDefinitions[0].Width =
new GridLength(leftRight, GridUnitType.Star);
contentGrid.ColumnDefinitions[1].Width =
new GridLength(centerLeftRight, GridUnitType.Star);
contentGrid.ColumnDefinitions[2].Width =
new GridLength(center, GridUnitType.Star);
contentGrid.ColumnDefinitions[3].Width =
new GridLength(centerLeftRight, GridUnitType.Star);
contentGrid.ColumnDefinitions[4].Width =
new GridLength(leftRight, GridUnitType.Star);
contentBorderMargin = contentPercentage;
CalculateContentBorderMargin();
InvalidateVisual();
}
private void CalculateContentBorderMargin()
{
if (contentBorder != null)
{
contentBorder.Margin = new Thickness(-(this.Width * contentBorderMargin),
0, -(this.Width * contentBorderMargin), 0);
}
}
Here is the Control Template for the Sophisticated ToggleSwitch control:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:wpfspark="clr-namespace:WPFSpark">
-->
<ControlTemplate x:Key="{ComponentResourceKey TypeInTargetAssembly=
wpfspark:ToggleSwitch, ResourceId=ToggleSwitchTemplate}"
TargetType="{x:Type wpfspark:ToggleSwitch}">
<ControlTemplate.Resources>
<Storyboard x:Key="BeginGlow">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="EndGlow">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Glow"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
-->
<wpfspark:ClipBorder Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
CornerRadius="{Binding Path=CornerRadius,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Name="PART_RootGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.4*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.4*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<i:Interaction.Behaviors>
<ei:FluidMoveBehavior AppliesTo="Children"
Duration="0:0:0.2">
<ei:FluidMoveBehavior.EaseX>
<QuarticEase EasingMode="EaseIn" />
</ei:FluidMoveBehavior.EaseX>
</ei:FluidMoveBehavior>
</i:Interaction.Behaviors>
-->
<Border Name="PART_ContentBorder"
Grid.Column="0"
CornerRadius="0"
Background="Transparent"
BorderThickness="0">
<Grid Name="PART_ContentGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.375*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.05*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.375*"></ColumnDefinition>
</Grid.ColumnDefinitions>
-->
-->
<Border x:Name="CheckedBorder"
Grid.Column="0"
Grid.ColumnSpan="2"
BorderThickness="0"
Margin="0"
CornerRadius="0"
Background="{Binding Path=CheckedBackground,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}">
</Border>
-->
<TextBlock x:Name="CheckedTextBlock"
Grid.Column="0"
Text="{Binding Path=CheckedText,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"
Foreground="{Binding Path=CheckedForeground,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
></TextBlock>
-->
-->
<Border x:Name="UncheckedBorder"
Grid.Column="3"
Grid.ColumnSpan="2"
BorderThickness="0"
Margin="0"
CornerRadius="0"
Background="{Binding Path=UncheckedBackground,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}">
</Border>
-->
<TextBlock x:Name="UncheckedTextBlock"
Grid.Column="4"
Text="{Binding Path=UncheckedText,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"
Foreground="{Binding Path=UncheckedForeground,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}">
</TextBlock>
-->
<wpfspark:ClipBorder x:Name="PART_Thumb"
Grid.Column="1"
Grid.ColumnSpan="3"
Margin="0"
BorderBrush="{Binding Path=ThumbBorderBrush,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
BorderThickness="{Binding Path=ThumbBorderThickness,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
CornerRadius="{Binding Path=ThumbCornerRadius,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}"
Background="{Binding Path=ThumbBackground,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.507*" />
<RowDefinition Height="0.493*" />
</Grid.RowDefinitions>
<Border x:Name="Glow"
Opacity="0"
HorizontalAlignment="Stretch"
Width="Auto"
Grid.RowSpan="2"
CornerRadius="{Binding Path=ThumbCornerRadius,
RelativeSource={RelativeSource
AncestorType=
{x:Type wpfspark:ToggleSwitch}}}">
<Border.Background>
<RadialGradientBrush>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.702"
ScaleY="2.743" />
<SkewTransform AngleX="0"
AngleY="0" />
<RotateTransform Angle="0" />
<TranslateTransform X="-0.368"
Y="-0.152" />
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop
Color="{Binding Path=ThumbGlowColor,
RelativeSource={RelativeSource
AncestorType=
{x:Type wpfspark:ToggleSwitch}}}"
Offset="0.1" />
<GradientStop Color="#44222222"
Offset="0.8" />
</RadialGradientBrush>
</Border.Background>
</Border>
<Border x:Name="Shine"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
Width="Auto"
CornerRadius="{Binding Path=ThumbShineCornerRadius,
RelativeSource={RelativeSource
AncestorType=
{x:Type wpfspark:ToggleSwitch}}}">
<Border.Background>
<LinearGradientBrush EndPoint="0.494,0.889"
StartPoint="0.494,0.028">
<GradientStop Color="#99FFFFFF"
Offset="0" />
<GradientStop Color="#33FFFFFF"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</wpfspark:ClipBorder>
</Grid>
</Border>
</Grid>
</wpfspark:ClipBorder>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked"
Value="false">
<Setter Property="Grid.Column"
TargetName="PART_ContentBorder"
Value="{Binding Path=TargetColumnInternal,
RelativeSource={RelativeSource
AncestorType={x:Type wpfspark:ToggleSwitch}}}" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Opacity"
Value="0.4" />
<Setter TargetName="UncheckedTextBlock"
Property="Foreground"
Value="LightGray"></Setter>
<Setter TargetName="CheckedTextBlock"
Property="Foreground"
Value="LightGray"></Setter>
</Trigger>
<Trigger Property="ToggleButton.IsPressed"
Value="True">
<Setter Property="Opacity"
TargetName="Shine"
Value="0.6" />
</Trigger>
<Trigger Property="ToggleButton.IsMouseOver"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BeginGlow}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource EndGlow}" />
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type wpfspark:ToggleSwitch}">
<Setter Property="Template"
Value="{StaticResource {ComponentResourceKey
TypeInTargetAssembly=wpfspark:ToggleSwitch,
ResourceId=ToggleSwitchTemplate}}" />
</Style>
</ResourceDictionary>
Update: WPFSpark v1.0
With the release of WPFSpark v1.0, the following changes have been incorporated into ToggleSwitch:
- Added the
IsCheckedLeft dependency property which indicates whether the checked content appears in the left or right side of the ToggleSwitch.
- Added the
CheckedToolTip property which is displayed when the ToggleSwitch is in the Checked state. Set this property to String.Empty( "" ) to prevent this tooltip from displaying.
- Added the
UncheckedToolTip property which is displayed when the ToggleSwitch is in the Unchecked state. Set this property to String.Empty( "" ) to prevent this tooltip from displaying.
Check out the latest source code available at CodePlex to get the latest ToggleSwitch.
ToggleSwitch Properties
| Dependency Property |
Type |
Description |
Default Value |
CheckedBackground |
Brush |
Gets or sets the Background of the CheckedBorder in the ToggleSwitch control. |
White |
CheckedForeground |
Brush |
Gets or sets the Foreground color of the CheckedText. |
Black |
CheckedText |
String |
Gets or sets the text that is displayed when the ToggleSwitch control is in the Checked state. |
String.Empty |
CheckedToolTip |
String |
Gets or sets the ToolTip that is displayed when the ToggleSwitch is in the Checked state. Set this property to String.Empty( "" ) to prevent this tooltip from displaying. |
String.Empty |
CornerRadius |
CornerRadius |
Gets or sets the CornerRadius of the outermost ClipBorder. |
0 |
IsCheckedLeft |
Boolean |
Gets or sets whether the checked content appears in the left or right side of the ToggleSwitch. |
True |
TargetColumnInternal |
Int32 |
Gets or sets the column in the RootGrid where the ContentGrid must be placed when the ToggleSwitch is in the Unchecked state. This property is used internally and should not be set by the user. |
0 |
ThumbBackground |
Brush |
Gets or sets the Background brush of the Thumb. |
Black |
ThumbBorderBrush |
Brush |
Gets or sets the color of the Thumb Border. |
Gray |
ThumbBorderThickness |
Thickness |
Gets or sets the thickness of the Thumb Border. |
0 |
ThumbCornerRadius |
CornerRadius |
Gets or sets the CornerRadius of the Thumb Border. |
0 |
ThumbGlowColor |
Color |
Gets or sets the Color of the glow over the Thumb when the mouse hovers over it. |
LawnGreen |
ThumbShineCornerRadius |
CornerRadius |
Gets or sets the CornerRadius of the Thumb Border's shine. |
0 |
ThumbWidth |
Double |
Gets or sets the width of the Thumb as a percentage of the Total width of the ToggleSwitch control. Value Range: 10 - 90 (inclusive). |
40 |
UncheckedBackground |
Brush |
Gets or sets the Background of the UncheckedBorder in the ToggleSwitch control. |
White |
UncheckedForeground |
Brush |
Gets or sets the Foreground color of the CheckedText. |
Black |
UncheckedText |
String |
Gets or sets the text that is displayed when the ToggleSwitch control is in the Unchecked state. |
String.Empty |
UncheckedToolTip |
String |
Gets or sets the ToolTip that is displayed when the ToggleSwitch is in the Unchecked state. Set this property to String.Empty( "" ) to prevent this tooltip from displaying. |
String.Empty |
Skinning the ToggleSwitch
You can skin the ToggleSwitch by modifying the above dependency properties. You can modify the background of the Checked and Unchecked states of the control. You can even modify the CornerRadius of the Thumb to get a variety of Thumb shapes ranging from rectangle to rounded rectangles and even to circles too!
Here are a few examples of the various skins of the ToggleSwitch control.

EndPoint
If you want to learn more about custom control development in WPF, I would suggest you read the book WPF Control Development Unleashed by Pavan Podila. It is deeply informative and contains lots of tips and tricks and other interesting facts regarding custom controls.
History
- December 21, 2011:
WPFSpark v1.0 released
- July 31, 2011:
WPFSpark v0.6 released