I am following along this awesome tutorial about custom controls, and in the fourth video of the playlist, Sean goes over visual states. In his AnalogClockStyle.xaml
, he demonstrates a simple visual state manager inside the control's grid, but I can imagine this is not viable for more intricately designed custom controls if you just want to analyse their control templates.
Is there a way to separate out the visual state manager from the control template's style file? I would ideally like to create folders for Custom Control *.cs
files, their control template *.xaml
files, their respective style *.xaml
files and finally their visual state manager files (if possible).
Here's what the current control template looks like:
<Style TargetType="local:AnalogClock">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:AnalogClock">
<ControlTemplate.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:GreaterThanMultiConverter x:Key="GreaterThanMultiConverter"/>
<converters:DivisionConverter x:Key="DivisionConverter"/>
</ControlTemplate.Resources>
<Grid x:Name="Clock" RenderTransformOrigin="0.5 0.5">
<Grid.RenderTransform>
<RotateTransform Angle="90"/>
</Grid.RenderTransform>
<!-- Move the Visual State Manager code to a separate file? -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TimeStates">
<VisualState x:Name="Day">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ClockFill"
Storyboard.TargetProperty="Color"
To="SkyBlue"/>
<ColorAnimation Storyboard.TargetName="HourStroke"
Storyboard.TargetProperty="Color"
To="Gold"/>
<ColorAnimation Storyboard.TargetName="MinuteStroke"
Storyboard.TargetProperty="Color"
To="Gold"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Night">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ClockFill"
Storyboard.TargetProperty="Color"
To="Black"/>
<ColorAnimation Storyboard.TargetName="HourStroke"
Storyboard.TargetProperty="Color"
To="White"/>
<ColorAnimation Storyboard.TargetName="MinuteStroke"
Storyboard.TargetProperty="Color"
To="White"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Christmas">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ClockFill"
Storyboard.TargetProperty="Color"
To="Green"/>
<ColorAnimation Storyboard.TargetName="HourStroke"
Storyboard.TargetProperty="Color"
To="Red"/>
<ColorAnimation Storyboard.TargetName="MinuteStroke"
Storyboard.TargetProperty="Color"
To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Move the Visual State Manager code to a separate file? -->
<Ellipse x:Name="PART_Clock" Stroke="Black" StrokeThickness="1">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Width" Value="{Binding ActualHeight, ElementName=Clock}"/>
<Setter Property="Height" Value="auto"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource GreaterThanMultiConverter}">
<MultiBinding.Bindings>
<Binding Path="ActualHeight" ElementName="Clock"/>
<Binding Path="ActualWidth" ElementName="Clock"/>
</MultiBinding.Bindings>
</MultiBinding>
</DataTrigger.Binding>
<DataTrigger.Setters>
<Setter Property="Height" Value="{Binding ActualWidth, ElementName=Clock}"/>
<Setter Property="Width" Value="auto"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
<Ellipse.Fill>
<SolidColorBrush x:Name="ClockFill" Color="White"/>
</Ellipse.Fill>
</Ellipse>
<Line x:Name="PART_HourHand" StrokeThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center" X1="0"
X2="{Binding ActualHeight, ElementName=PART_Clock, Converter={StaticResource DivisionConverter}, ConverterParameter=-4}">
<Line.Stroke>
<SolidColorBrush x:Name="HourStroke" Color="Black"/>
</Line.Stroke>
</Line>
<Line x:Name="PART_MinuteHand" StrokeThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center" X1="0"
X2="{Binding ActualHeight, ElementName=PART_Clock, Converter={StaticResource DivisionConverter}, ConverterParameter=-2.5}">
<Line.Stroke>
<SolidColorBrush x:Name="MinuteStroke" Color="Black"/>
</Line.Stroke>
</Line>
<Line x:Name="PART_SecondHand" Visibility="{TemplateBinding ShowSeconds, Converter={StaticResource BooleanToVisibilityConverter}}" Stroke="Red" StrokeThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center" X1="0"
X2="{Binding ActualHeight, ElementName=PART_Clock, Converter={StaticResource DivisionConverter}, ConverterParameter=-2.5}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>