0

thanks for taking a look. I'm trying to make a button in WPF shake when pressed, if a checkbox is checked somewhere else. I tried to do this solely in XAML but couldn't figure out how to check both for click as a trigger and the checkbox. Here's my XAML code:

<Style TargetType="{x:Type Button}">
 <Setter Property="RenderTransformOrigin"
         Value="0.5 0.5" />
 <Setter Property="RenderTransform">
   <Setter.Value>
     <RotateTransform />
   </Setter.Value>
 </Setter>

 <Style.Triggers>

   <MultiTrigger>

     <MultiTrigger.Conditions>
       <Condition Property='IsPressed'
                  Value='True' />
     </MultiTrigger.Conditions>

     <MultiTrigger.EnterActions>
       <BeginStoryboard>
         <Storyboard TargetProperty="RenderTransform.Angle">
           <DoubleAnimation From="0"
                            To="5"
                            Duration="0:0:0.05"
                            AutoReverse="True"
                            FillBehavior="Stop" />
           <DoubleAnimation BeginTime="0:0:0.05"
                            From="5"
                            To="-5"
                            Duration="0:0:0.1"
                            AutoReverse="True"
                            FillBehavior="Stop" />
           <DoubleAnimation BeginTime="0:0:0.2"
                            From="-5"
                            To="0"
                            Duration="0:0:0.1"
                            AutoReverse="False"
                            FillBehavior="Stop" />
         </Storyboard>
       </BeginStoryboard>
     </MultiTrigger.EnterActions>

   </MultiTrigger>
 </Style.Triggers>

This makes buttons always shake when pressed. To get it to work conditionally I figured I should implement this in the codebehind. Once I get the animation working, it should be as simple as adding an if statement, I think.

MainWindow : Window

{

    private Storyboard myStoryboard;

    public MainWindow()

    {

        InitializeComponent();

        DoubleAnimation myDoubleAnimation = new DoubleAnimation();

        myDoubleAnimation.From = 0.0;
        myDoubleAnimation.To = 20.0;

        myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));

        myDoubleAnimation.AutoReverse = true;

        myStoryboard = new Storyboard();

        myStoryboard.Children.Add(myDoubleAnimation);
        Storyboard.SetTargetName(myDoubleAnimation, HelpButton.Name);
        Storyboard.SetTargetProperty(myDoubleAnimation, new 
        PropertyPath(RotateTransform.AngleProperty));
        HelpButton.Click += ShakeObject;

    }

private void ShakeObject(object sender, RoutedEventArgs e)
    {
        myStoryboard.Begin(this);
    }
}

I'd expect this code to rotate my button named 'HelpButton' (in XAML) by 20 degrees then back, but no such luck.

I can execute a single RotateTransform with .BeginAnimation(RotateTransform.AngleProperty, myDoubleAnimation); but I want to do several rotations in succession (to simulate shaking).

Any help is appreciated! Thanks.

B-H
  • 57
  • 1
  • 9
  • 2
    [Shaking](https://stackoverflow.com/q/31918334/1997232)? – Sinatr Jul 19 '18 at 15:07
  • Rotate back and forth a couple times. That animation looks really cool, but I'd be more than happy with just rotating to +10 degress, then from there to -10 degrees, then from there to 0. – B-H Jul 19 '18 at 15:09
  • 1
    The 2d *shaking* effect could be achieved using single animation with added [easing function](https://learn.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/easing-functions). – Sinatr Jul 19 '18 at 15:25
  • Thanks, I'll take a look! – B-H Jul 19 '18 at 15:41

2 Answers2

1

You need to add the condition on the checkbox and change the MultiTringger in MultiDataTrigger. Here is the code

<Style TargetType="{x:Type Button}">
            <Setter Property="RenderTransformOrigin" Value="0.5 0.5" />
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <RotateTransform />
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding ElementName=btn , Path=IsPressed}" Value="True" />
                        <Condition Binding="{Binding ElementName=chk , Path=IsChecked}" Value="True" />
                    </MultiDataTrigger.Conditions>

                    <MultiDataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard TargetProperty="RenderTransform.Angle">
                                <DoubleAnimation From="0"
                        To="5"
                        Duration="0:0:0.05"
                        AutoReverse="True"
                        FillBehavior="Stop" />
                                <DoubleAnimation BeginTime="0:0:0.05"
                        From="5"
                        To="-5"
                        Duration="0:0:0.1"
                        AutoReverse="True"
                        FillBehavior="Stop" />
                                <DoubleAnimation BeginTime="0:0:0.2"
                        From="-5"
                        To="0"
                        Duration="0:0:0.1"
                        AutoReverse="False"
                        FillBehavior="Stop" />
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiDataTrigger.EnterActions>

                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
  • This looks great, thanks! Where do you recommend placing this style, if I want to use it on buttons across different usercontrols? If I place it in App.xaml it doesn't work, I think because the checkbox is in its own view. (I did do selfbinding on the IsPressed) Is there a way I could reference that specific button on the App.xaml level? – B-H Jul 20 '18 at 10:19
  • I'm going to look into viewmodels, I think that might offer some solution – B-H Jul 20 '18 at 10:22
  • After reading a guide I could do it, thank you! It was this one: https://www.codeproject.com/Articles/1112919/MVVM-for-beginners – B-H Jul 20 '18 at 17:16
0

One solution I found is to apply my XAML style to my button when IsChecked triggers for my checkbox, and then remove the style if its unchecked.

B-H
  • 57
  • 1
  • 9