Set button as selected state and change style
button, c#, styles, visualstatemanager, wpf
Solution
`VisualStates` should be declared on the root element of the `ControlTemplate`. With the following code,
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="FillBrush" Color="Magenta" />
<Color x:Key="StateBrush" >#a3bfb1</Color>
<Style x:Key="CategoryButtonStyle" TargetType="{x:Type Button}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="Green" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" x:Name="root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TabPath"
Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource StateBrush}">
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="grid">
<Path x:Name="TabPath" StrokeThickness="1"
Stroke="Blue"
Fill="{StaticResource FillBrush}" Canvas.Left="16.75"
Canvas.Top="14"
Width="50"
Height="40"
Data="F1 M 26.75,24L 16.75,34L 23.5,34L 34,24L 23.5,14L 16.75,14L 26.75,24 Z ">
<Path.LayoutTransform>
<!-- For some reason -->
<ScaleTransform ScaleY="-1"/>
</Path.LayoutTransform>
</Path>
<ContentPresenter x:Name="buttonContent" Margin="10,2,10,2" VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button x:Name="test" Style="{StaticResource CategoryButtonStyle}" Content="Test" VerticalAlignment="Center" Width="200px" BorderBrush="#888" BorderThickness="1px"/>
</Grid>
this code will change the state as intended.
VisualStateManager.GoToState(test, "TestState", true);
Make changes to the template as required, but make sure you put the VisualState declaration in the Root element of the `ControlTemplate` (`Border` in this example)
EDIT: I've updated the Selected `VisualState`'s transition declaration with correct property path. Let me know if it solves your problem.
Problem
This is my actual button style: ``` <Style x:Key="CategoryButtonStyle" TargetType="{x:Type Button}"> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Padding" Value="1"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid x:Name="grid"> <Path x:Name="TabPath" StrokeThickness="2" Margin="{Binding ElementName=buttonContent, Converter={x:Static c:ContentToMarginConverter.Value}}" Stroke="{StaticResource BorderBrush1}" Fill="{StaticResource TabItemPathBrush}"> <Path.Data> <PathGeometry> <PathFigure IsClosed="False" StartPoint="1,0" Segments="{Binding ElementName=buttonContent, Converter={x:Static c:ContentToPathConverter.Value}}"> </PathFigure> </PathGeometry> </Path.Data> <Path.LayoutTransform> <!-- For some reason --> <ScaleTransform ScaleY="-1"/> </Path.LayoutTransform> </Path> <Rectangle x:Name="TabItemTopBorder" Height="2" Visibility="Visible" VerticalAlignment="Bottom" Fill="{StaticResource BorderBrush1}" Margin="{Binding ElementName=TabPath, Path=Margin}" /> <ContentPresenter x:Name="buttonContent" Margin="10,2,10,2" VerticalAlignment="Center" TextElement.Foreground="{StaticResource ForegroundBrush}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsPressed" Value="True"> <Setter Property="Fill" TargetName="TabPath"> <Setter.Value> <SolidColorBrush Color="#FFe4f6fa"/> </Setter.Value> </Setter> <Setter Property="BitmapEffect"> <Setter.Value> <DropShadowBitmapEffect Direction="302" Opacity="0.4" ShadowDepth="2" Softness="0.5"/> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" TargetName="grid" Value="0.25"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> ``` and I need add code that I could set button to selected state which looks like when button is pressed. I was thinking about using VisualStateManager but I am not sure if it's good way and how can I do this. I've started with something like this: ``` <VisualStateManager.VisualStateGroups> <VisualState x:Name="Normal" /> <VisualState x:Name="Selected"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TabPath" Storyboard.TargetProperty="Fill"> <DiscreteObjectKeyFrame KeyTime="0" Value="#FFe4f6fa" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateManager.VisualStateGroups> ``` But It's not working. I just don't know what to use in storyboard. Edit - Almost working: ``` <VisualState x:Name="Selected"> <Storyboard> <ColorAnimation Storyboard.TargetName="TabPath" Storyboard.TargetProperty="Fill.(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" To="#FFe4f6fa" Duration="0:0:0" /> <ColorAnimation Storyboard.TargetName="TabPath" Storyboard.TargetProperty="Fill.(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" To="#FFa9cde7" Duration="0:0:0" /> </Storyboard> </VisualState> ``` Forget to add my brushes: ``` <LinearGradientBrush x:Key="TabItemSelectedPathBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="#FFe4f6fa" Offset="0"/> <GradientStop Color="#FFa9cde7" Offset="1"/> </LinearGradientBrush> <LinearGradientBrush x:Key="TabItemPathBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="#FFa9cde7" Offset="0"/> <GradientStop Color="#FF3164a5" Offset="1"/> </LinearGradientBrush> ```