I'm working on a custom button for my project.
I'm not using a default Button
but just a ContentControl
with a ControlTemplate
assigned to it.
For the beginning just a simple template:
<ControlTemplate x:Key="MySampleTemplate">
<Image x:Name="img" Source="/AppName;component/Res/Img/normalstate.png" />
</ControlTemplate>
Now I would like to animate the image by using VisualStateManager
.
First I created a "Hover" and a "Normal" state:
<ControlTemplate x:Key="MySampleTemplate">
<Image x:Name="img" Source="/AppName;component/Res/Img/normalstate.png">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Hover">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="img" Storyboard.TargetProperty="Source">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="/AppName;component/Res/Img/hoverstate.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Image>
</ControlTemplate>
In Code behind:
btnSampleButton.MouseEnter += (s,e) => VisualStateManager.GoToState(btnSampleButton, "Hover", false);
btnSampleButton.MouseLeave += (s,e) => VisualStateManager.GoToState(btnSampleButton, "Normal", false);
Everything works just fine. If I hover over the button hoverstate.png
is shown and if I don't hover over normalstate.png
is shown.
Now I would like to animate LeftMouseButtonDown
and LeftMouseButtonUp
to achieve a pressing animation if the user click on the button.
I created a VisualState
called "Pressed" and just set it up like "Hover" (just replaced hoverstate.png with pressedstate.png).
In the code behind I did this:
btnSampleButton.MouseLeftButtonDown += (s,e) => VisualStateManager.GoToState(btnSampleButton, "Pressed", false);
btnSampleButton.MouseLeftButtonUp += (s,e) => VisualStateManager.GoToState(btnSampleButton, btnSampleButton.IsMouseOver ? "Hover" : "Normal", false);
However it does not work. MouseEnter
and MouseLeave
work fine but I can't see any changes to the button if I press/release my left mouse button.
Do you have any advice to get it work?
Edit: Control:
<ContentControl x:Name="btnSampleButton" Template="{StaticResource SamplButtonTemplate}" />
ControlTemplate:
<ControlTemplate x:Key="SamplButtonTemplate">
<Image x:Name="Image" Source="/AppName;component/Res/Img/normalstate.png">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Hover">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="Image" Storyboard.TargetProperty="Source">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="/AppName;component/Res/Img/hoverstate.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0" FillBehavior="Stop"
Storyboard.TargetName="Image" Storyboard.TargetProperty="Source">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="/AppName;component/Res/Img/pressedstate.png" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Image>
</ControlTemplate>
Code behind:
btnSampleButton.MouseEnter += (s, e) => VisualStateManager.GoToState(btnSampleButton, "Hover", false);
btnSampleButton.MouseLeave += (s, e) => VisualStateManager.GoToState(btnSampleButton, "Normal", false);
btnSampleButton.PreviewMouseLeftButtonDown +=
(s, e) => VisualStateManager.GoToState(btnSampleButton, "Pressed", false);
btnSampleButton.PreviewMouseLeftButtonUp +=
(s, e) => VisualStateManager.GoToState(btnSampleButton, btnSampleButton.IsMouseOver ? "Hover" : "Normal", false);
MouseLeftButtonDown
and MouseLeftButtonUp
gets swallowed by Click
event of Button that's why these events are never raised for button and no change in VisualState.
Instead hook corresponding Preview events i.e. PreviewMouseLeftButtonDown
and PreviewMouseLeftButtonUp
:
btnSampleButton.PreviewMouseLeftButtonDown += (s,e) =>
VisualStateManager.GoToState(btnSampleButton, "Pressed", false);
btnSampleButton.PreviewMouseLeftButtonUp += (s,e) =>
VisualStateManager.GoToState(btnSampleButton, btnSampleButton.IsMouseOver ?
"Hover" : "Normal", false);
Remove FillBehavior="Stop"
from second StoryBoard and your code works fine.
<VisualState Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0"
FillBehavior="Stop" <-- Remove this
Storyboard.TargetName="Image"
Storyboard.TargetProperty="Source">