Question

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);
Was it helpful?

Solution

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">
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top