4
votes

This may be animation related. I have a WPF control whose width and height I'm animating through several different storyboards. I create the storyboards and then call Begin() on them. I've provided code for how the storyboards look below.

I want to re-evaluate the control size on some event (e.g. window resize) so that it is different from the value that was animated. I attempt to handle this on SizeChanged manually (after the animation has run) by setting the Width and Height properties of my control. The debugger shows that those values are not set (the original values remain).

When I inspect the WPF through Snoop, the Width and Height rows are highlighted in a peach/orange color and trying to set the values through it again does not persist it (the original value is shown when I focus away. My guess is that my animation is somehow overriding manual changes to the property but I'm not sure if this is true or how to solve it.

Storyboard Class

public class MyAnimationClass
{
    private Storyboard _myStoryboard;
    private DoubleAnimation _animation1;
    private DoubleAnimation _animation2;
    private DoubleAnimation _animation3;

    private void InitializeStoryboard()
    {
        _myStoryboard = CreateMyStoryboard(out _animation1, out _animation2, out _animation3);
    }

    private Storyboard CreateMyStoryboard(out DoubleAnimation animation1, out DoubleAnimation animation2, out DoubleAnimation animation3)
    {
        var myStoryboard = new Storyboard();

        // create animations
        animation1 = new DoubleAnimation { Duration = new TimeSpan(0, 0, 0, 0, 250), From = 0, To = 0 };
        animation2 = new DoubleAnimation { BeginTime = new TimeSpan(), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 35 };
        animation3 = new DoubleAnimation { BeginTime = new TimeSpan(0, 0, 0, 0, 250), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 0 };

        Storyboard.SetTargetProperty(animation1, new PropertyPath(FrameworkElement.WidthProperty));
        Storyboard.SetTargetProperty(animation2, new PropertyPath(FrameworkElement.HeightProperty));
        Storyboard.SetTargetProperty(animation3, new PropertyPath(FrameworkElement.HeightProperty));

        myStoryboard.Children.Add(animation1);
        myStoryboard.Children.Add(animation2);
        myStoryboard.Children.Add(animation3);

        return myStoryboard;
    }

    public void Animate(Control controlToAnimate)
    {
        // ....

        var finalWidth = CalculateFinalWidth();
        var finalHeight = CalculateFinalHeight();

        _animation1.To = finalWidth;
        _animation3.To = finalHeight;
        _myStoryboard.Begin(controlToAnimate);
    }
}

When I want to animate something, I call Animate() on the instance of my MyAnimationClass class.

Thoughts?

1
Seems to me you'll need to stop these storyboards first.Federico Berasategui
@HighCore Ah I thought it stopped automatically. I just found this MSDN article, which tells me I need to set FillBehavior to Stop to have it stop on completion: msdn.microsoft.com/en-us/library/aa970493.aspxsohum
Hmm, if I set FillBehavior to Stop and then resize the window (which triggers setting control's width and height, calling UpdateLayout and calling InvalidateVisual on the control) the animation no longer animates to the desired width and height--but the one set by the resize. Do I need to create a new storyboard for each animation?sohum
What are you trying to do? handling the window resized event is normally not required..Federico Berasategui
I want to resize the control when the window is resized manually. Basically, when I perform an action the animation happens. But after that I want the control's dimensions to be handled manually (by setting Width and Height). However, when I run the animation again, I want it to animate across the calculated values, not the Width and Height I set. It seems if I set FillBehavior to Stop, the Width and Height are Double.NaN. When I set Width and Height manually, those values are set and the animation values are ignored.sohum

1 Answers

2
votes

This ended up being a pretty simple fix. The value wasn't changing because of FillBehavior controlling the property value. However, simply changing it to FillBehavior.Stop didn't solve my problem because when my non-animation code set width/height, the next time my animation ran it would animate to the width/height I wanted and then default back to the set height. This was solved by setting the width/height of the control after calculation and before animation:

public void Animate(Control controlToAnimate)
{
    // ....

    var finalWidth = CalculateFinalWidth();
    var finalHeight = CalculateFinalHeight();

    // set values here so after animation they stay
    controlToAnimate.Width = finalWidth;
    controlToAnimate.Height = finalHeight;

    _animation1.To = finalWidth;
    _animation3.To = finalHeight;
    _myStoryboard.Begin(controlToAnimate);
}