How to animate the StartPoint of LinearGradient - wpf

I have a LinearGradientBrush used as an OpacityMask and I want my animation to rotate the gradient, so I'm trying to animate the position of the StartPoint and EndPoint but I can't make it work for hours :(
<Style x:Key="NewContentStyle" TargetType="ContentPresenter">
<Setter Property="OpacityMask">
<Setter.Value>
<LinearGradientBrush x:Name="FillGradient" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Storyboard x:Key="NewContentStoryboard">
<PointAnimation Storyboard.TargetProperty="StartPoint" Storyboard.TargetName="FillGradient" From="0.5 0" To="0 0.5" Duration="00:00:1" />
<PointAnimation Storyboard.TargetProperty="EndPoint" Storyboard.TargetName="FillGradient" From="1 0.5" To="0 0.5" Duration="00:00:1"/>
</Storyboard>
I get an error "'FillGradient' name cannot be found in the name scope of 'System.Windows.Controls.ContentPresenter'."

Please try this:
<Storyboard x:Key="NewContentStoryboard">
<PointAnimation Storyboard.TargetProperty="OpacityMask.(LinearGradientBrush.StartPoint)" From="0.5 0" To="0 0.5" Duration="00:00:1" />
<PointAnimation Storyboard.TargetProperty="OpacityMask.(LinearGradientBrush.EndPoint)" From="1 0.5" To="0 0.5" Duration="00:00:1"/>
</Storyboard>

Related

Unset databound property when animation completes in WPF

I would like to set my databound property IsFlashing to False when my animation completes.
<Border BorderThickness="1"
Height="15"
Width="20"
CornerRadius="2"
BorderBrush="Black"
DockPanel.Dock="Top"
Grid.Row="1" >
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsFlashing}" Value="True" x:Name="dataTrigger">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard FillBehavior="Stop" RepeatBehavior="1x" x:Name="startStoryBoard">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Background"
Duration="0:0:4" RepeatBehavior="1x">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Orange" Offset="0.9" />
<GradientStop Color="Red" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<!-- how can I set my bound property "IsFlashing" to false when we exit here ? -->
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFFFFF" Offset="0.0" />
<GradientStop Color="#ADD8E6" Offset="0.9" />
<GradientStop Color="#8aacb8" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<TextBlock Foreground="Black" Text="{Binding Path=MarkerCode}" FontFamily="Segoe UI" FontSize="12" TextAlignment="Center" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="3" Color="White" />
</TextBlock.Effect>
</TextBlock>
</Border>
Listen to the Completed event of the ObjectAnimationUsingKeyFrames
ExitActions are what happens when the trigger condition is no longer met (in this case when IsFlashing returns to false), which is not the same the animation completing.

WPF border animation not working

I am trying to put an animation on a border as follows
<LinearGradientBrush x:Key="RedButtonBrushUp" StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#ffaaaa" Offset="0"/>
<GradientStop Color="#cc6666" Offset="0.6"/>
<GradientStop Color="#bb2222" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="ButtonBrushUp" StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#aaccff" Offset="0"/>
<GradientStop Color="#7799ff" Offset="0.6"/>
<GradientStop Color="#555599" Offset="1"/>
</LinearGradientBrush>
<Border x:Name="BorderUp" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" Background="{StaticResource RedButtonBrushUp}">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Storyboard.TargetName="BorderUp"
Storyboard.TargetProperty="Background"
RepeatBehavior="Forever"
AutoReverse="True"
To="{StaticResource ButtonBrushUp}"
Duration="0:0:0.5" ></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
</Border>
But it says {StaticResource ButtonBrushUp} is an invalid type for this. What am I doing wrong?
The To can't accept such a change needed for the gradient brush stops.
Here is a working example of what you are trying to do
<Window.Resources>
<Storyboard x:Key="OnLoaded1">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="myBorder">
<EasingColorKeyFrame KeyTime="0:0:1" Value="#FFC53838"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="myBorder">
<BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<StackPanel x:Name="stackPanel" Orientation="Vertical" HorizontalAlignment="Center">
<Border x:Name="myBorder" Background="#99FFFFFF" BorderThickness="3"
Margin="0,60,0,20" Padding="20" >
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<TextBlock>
This example shows how to have a border change color after an initial load.
</TextBlock>
</Border>
</StackPanel>

EventTrigger RoutedEvent amimation in wpf xaml

I want an animation to be launched when MyObject.IsGlowing = true so I did this (I'm in a <DataTemplate> if that can help)
<Ellipse Width="100" Height="100" Name="MyEllipse">
<Ellipse.Fill>
<RadialGradientBrush >
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.5" Color="red" />
<GradientStop Offset="1" Color="red"/>
</RadialGradientBrush >
</Ellipse.Fill>
<Ellipse.Triggers>
<DataTrigger Binding="{Binding Source=IsGlowing}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="MyBeginStoryBoard">
<Storyboard Name="MyStoryBoard" >
//Animation
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Ellipse.Triggers>
</Ellipse>
but I got this error "Triggers collection members must be of type EventTrigger" so I changed it to
<Ellipse Width="100" Height="100" Name="MyEllipse">
<Ellipse.Fill>
<RadialGradientBrush >
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.5" Color="red" />
<GradientStop Offset="1" Color="red"/>
</RadialGradientBrush >
</Ellipse.Fill>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="?">
<BeginStoryboard Name="MyBeginStoryBoard">
<Storyboard Name="MyStoryBoard" >
//Animation
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
But i have no idea what to put in RoutedEvent...
You aren't allowed DataTriggers to be directly used/specified within an elements Triggers collection. However, you can use a Style to apply one.
http://www.thejoyofcode.com/Help_Why_cant_I_use_DataTriggers_with_controls_in_WPF.aspx

Silverlight Bind VisualState to different Targets

I'm using the following border style:
<!-- Border Style -->
<Style TargetType="Border">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5, 1" StartPoint="0.5 ,0" MappingMode="RelativeToBoundingBox">
<GradientStop Color="#00000000" Offset="0" />
<GradientStop Color="#FFFFFEBB" Offset="0.116"/>
<GradientStop Color="#FFFFFEBB" Offset="0.897"/>
<GradientStop Color="#00000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Opacity" Value="0"/>
<Setter Property="OpacityMask">
<Setter.Value>
<LinearGradientBrush EndPoint="1.0 ,0.5" StartPoint="0.0 ,0.5" MappingMode="RelativeToBoundingBox">
<GradientStop/>
<GradientStop Color="#FF000000" Offset="0.1"/>
<GradientStop Color="#FF000000" Offset="0.9"/>
<GradientStop Color="#00000000" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="RenderTransform">
<Setter.Value>
<CompositeTransform ScaleX="1.03" ScaleY="1.01"/>
</Setter.Value>
</Setter>
</Style>
There are three Borders in my application. I want to animate the opacity of the border when the mouse cursor is entering the border. In order to do that, I'm using a VisualState:
<VisualState x:Name="MouseOverState">
<Storyboard>
<DoubleAnimation To="1" Storyboard.TargetProperty="(UIElement.Opacity)" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
Do I need to define three different VisualStates and set the Storyboard.TargetName property? Or is there a way to use the same VisualState for many objects?
PS:
I know that there is a TargetName and TargetObject Property in the GoToStateAction, but I can't get it to work:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<ei:GoToStateAction StateName="MouseOverState" TargetName="border0"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<ei:GoToStateAction StateName="DefaultState" TargetName="border0"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I'd be inclined to create a custom control deriving from the ContentControl.
In themes\generic.xaml
<Style TargetType="local:MyBorder">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5, 1" StartPoint="0.5 ,0" MappingMode="RelativeToBoundingBox">
<GradientStop Color="#00000000" Offset="0" />
<GradientStop Color="#FFFFFEBB" Offset="0.116"/>
<GradientStop Color="#FFFFFEBB" Offset="0.897"/>
<GradientStop Color="#00000000" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="OpacityMask">
<Setter.Value>
<LinearGradientBrush EndPoint="1.0 ,0.5" StartPoint="0.0 ,0.5" MappingMode="RelativeToBoundingBox">
<GradientStop/>
<GradientStop Color="#FF000000" Offset="0.1"/>
<GradientStop Color="#FF000000" Offset="0.9"/>
<GradientStop Color="#00000000" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="RenderTransform">
<Setter.Value>
<CompositeTransform ScaleX="1.03" ScaleY="1.01"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyBorder">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Opacity="0"
>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation To="1" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup >
</vsm:VisualStateManager>
<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Cursor="{TemplateBinding Cursor}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You just need to add the MouseEnter MouseLeave set the visual state of the control accordingly.
Now you can simply drop local:MyBorder where you need one of these borders.

Slider On/Off Switch in WPF

I am looking for a WPF tutorial on creating a slide ON/OFF switch like on the iPhone.
Here is an example (the "Send all traffic" option) https://secure-tunnel.com/support/software_setup/iphone/images/iphone_vpn_settings.jpg
I haven't seen a tutorial on this exact problem, but i guess you can start by launching Expression Blend and putting a CheckBox on it. Then select the CheckBox, go to main menu - Object -> Edit Style -> Edit a Copy
This will make Blend generate the default style of CheckBox so you're able to modify it. Look at how things work there and you'll be able to achieve some results.
Basically (besides colors and brushes stuff) you'll need to look at triggers hooked up to the IsChecked property.
E.g. when IsChecked is True you move the rectangle to one of the sides, show the ON word and hide the OFF word. To animate this you only need to add trigger in- and out- animations.
UPD:
I've spent 10-15 minutes in blend to make a "prototype":
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="CheckBoxIPhone.Window1"
x:Name="Window"
Title="Window1"
Width="320"
Height="240"
FontFamily="Segoe UI"
FontSize="20"
WindowStartupLocation="CenterScreen"
>
<Window.Resources>
<Style x:Key="CheckBoxStyle1" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="OnChecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="25"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnUnchecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(FrameworkElement.Margin)">
<SplineThicknessKeyFrame KeyTime="00:00:00.3000000" Value="1,1,1,1"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<DockPanel x:Name="dockPanel">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center"/>
<Grid Margin="5,5,0,5" Width="50" Background="#FFC0CCD9">
<TextBlock Text="ON" TextWrapping="Wrap" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right" Margin="0,0,3,0"/>
<TextBlock HorizontalAlignment="Left" Margin="2,0,0,0" FontSize="12" FontWeight="Bold" Text="OFF" TextWrapping="Wrap"/>
<Border HorizontalAlignment="Left" x:Name="slider" Width="23" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3" RenderTransformOrigin="0.5,0.5" Margin="1,1,1,1">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Border.RenderTransform>
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FF4490FF" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF8AB4FF" Offset="1"/>
<GradientStop Color="#FFD1E2FF" Offset="0"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Center" Content="CheckBox"/>
</Grid>
</Window>
I'm also suggesting you to read about Styles and Templates in WPF if you're interested.
I created some styles based on the post by arconaut in orange and blue.
Screenshot:
I wanted my style to closer match the On/Off Switch style of iOS devices. One difference in this style is, that the sliding animation does only slide the switch and not the indicators below. Maybe if i can find some time I will modify it that way. Until then I want to share my result. It's not perfect, but here is the code.
<LinearGradientBrush x:Key="CheckedBlue" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FF285AB3" Offset="0" />
<GradientStop Color="#FF4184EC" Offset="0.5" />
<GradientStop Color="#FF558BED" Offset="0.5" />
<GradientStop Color="#FF7DACF0" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="CheckedOrange" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFCA6A13" Offset="0" />
<GradientStop Color="#FFF67D0C" Offset="0.2" />
<GradientStop Color="#FFFE7F0C" Offset="0.2" />
<GradientStop Color="#FFFA8E12" Offset="0.5" />
<GradientStop Color="#FFFF981D" Offset="0.5" />
<GradientStop Color="#FFFCBC5A" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="CheckedOrangeBorder" Color="#FF8E4A1B" />
<SolidColorBrush x:Key="CheckedBlueBorder" Color="#FF143874" />
<Style x:Key="OrangeSwitchStyle" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="OnChecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="53" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnUnchecking">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<DockPanel x:Name="dockPanel">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center" />
<Grid>
<Border x:Name="BackgroundBorder" BorderBrush="#FF939393" BorderThickness="1" CornerRadius="3" Height="27" Width="94">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFB5B5B5" Offset="0" />
<GradientStop Color="#FFDEDEDE" Offset="0.1" />
<GradientStop Color="#FFEEEEEE" Offset="0.5" />
<GradientStop Color="#FFFAFAFA" Offset="0.5" />
<GradientStop Color="#FFFEFEFE" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition /><ColumnDefinition />
</Grid.ColumnDefinitions>
<Ellipse x:Name="Off" Width="14" Height="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Line x:Name="On" X1="0" Y1="0" X2="0" Y2="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Border>
<Border BorderBrush="#FF939393" HorizontalAlignment="Left" x:Name="slider" Width="41" Height="27" BorderThickness="1" CornerRadius="3" RenderTransformOrigin="0.5,0.5" Margin="0">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" />
<SkewTransform AngleX="0" AngleY="0" />
<RotateTransform Angle="0" />
<TranslateTransform X="0" Y="0" />
</TransformGroup>
</Border.RenderTransform>
<Border.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0" />
<GradientStop Color="#FFCDCDCD" Offset="0.1" />
<GradientStop Color="#FFFBFBFB" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard" />
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard" />
</Trigger.EnterActions>
<Setter TargetName="On" Property="Stroke" Value="White" />
<Setter TargetName="Off" Property="Stroke" Value="White" />
<!-- Change Orange or Blue color here -->
<Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource CheckedOrange}" />
<Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource CheckedOrangeBorder}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!-- ToDo: Add Style for Isenabled == False -->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A few open source ToggleSwitches:
ToggleSwitch looks good, available by NuGet, too.
MahApps ToggleSwitch is a part of bigger MahApps library of Metro like controls.
I just posted an entry in regards to this which provides a proper sliding action, full configurability and doesn't require to be a fixed size (got annoyed as I couldn't find anything on the web that provided a solution like that).
You can find it here: http://itsallaboutthexaml.blogspot.com/2012/01/variables-in-animation.html
Well I set out to accomplish this same task but the examples fell a little short of production code. For instance what happens if you put text into the control like On/Off or a localized version of the text, answer is you have to define the size of the control because you cannot modify an animation or template triggers after you have rendered the control. This gives you a one-size-fits-all solution that will not work with localized text.
My solution was to create the template for the control dynamically using the control's Loaded event and the FrameworkElementFactory class. I have to say it was by far complicated but could be achieved. Simply put, in your code behind, create a template as described, setup dependency properties for your on/off text, use the text metrics to determine the control's width, height and animation values.
I'm sorry that I cannot post the solution since it belongs to Avanquest now. :(
Look for it in SystemSuite and Fix-It 12.
I like the nice prototype from arconaut and I added some code to get the border rounded.
You have to remove the "Background" property from the Grid declaration and add this lines between the Grid declaration and the first TextBlock declaration:
<Border
x:Name="back"
CornerRadius="3,3,3,3"
BorderThickness="1"
BorderBrush="#FFC0CCD9"
>
<Rectangle Fill="#FFC0CCD9"/>
</Border>

Resources