To understand the behavior, you need to know how animation works in the WPF property system: animation does not work, setting the property for different values ββover time. They work by providing an effective value for a property that temporarily takes precedence over a "base" value. This is a subtle difference, but it is what makes you peel off here.
When you first come across an animation system, most people think it works by repeatedly calling the "set" accessor for a property. But this is not so - if you set the property this way before starting the animation, the original value that you set remains in place. It's just that getter will return the value provided by the animation system, instead of returning a "local" value. In fact, you can even change the βlocalβ value by setting the property during the animation, but this local value will not become visible until the animation stops.
Actually, the ownership system does a lot of this - it's not just animation. This reference topic contains 11 different places from which a property value can come. Animation is the second highest priority. Properties set in the usual way through the set accessory (or through attributes in Xaml) are the next highest priority, but you can see that templates, styles, and triggers provide other sources if there is no local property value.
The WPF animation system has the concept of a βbaseβ value and essentially the value of the next highest priority available after the current animated value. If you have a local value, this will be the base value, but if the base value is not obtained from one of the other sources listed in this article.
The result of all that there is no easy way to do what you are trying to do. I think you want the animation to run until completion, and that the property retains the final animation value until you set a local value for something else.
If you tell the animation to stop after it is completed, the effective value will revert to the base value. (As you say in the commentary, it shrinks after the animation finishes.) And if you let the animation know that it will be completed (this is the default behavior), then the animation will forever provide a value that has higher priority than local values, so you see that manually resizing the button no longer works. Thus, none of the options does what you want.
There are two ways to handle this. @ responderNS5 posted one - handle the completion of the animation, change the local value to reflect the final value of the animation, and then stop the animation. (You might think that this is a kind of demotion β it will convert it from a high-priority but transitory value of the property provided by the animation to a slightly lower priority but more constant local value.) I would be inclined to change the code a bit:
private void myDoubleAnimation_Completed(object sender, EventArgs e) {
What I changed here is that the code no longer tries to guess where the animation system ended up - it just reads any value that the animation system sets for this property and makes it a new local value. I prefer += 10 in the Completed handler, which for me looks like a slightly fragile duplication of logic.
Another way to handle this is to remove the animation where you are trying to update the property:
private void _resizeButton_Click(object sender, RoutedEventArgs e) { double currentHeight = button.Height; button.BeginAnimation(Button.HeightProperty, null); button.Height = currentHeight + 10; } private void _animateButton_Click(object sender, RoutedEventArgs e) { DoubleAnimation animation = new DoubleAnimation { By = 10, Duration = new Duration(TimeSpan.FromSeconds(1)) }; button.BeginAnimation(Button.HeightProperty, animation); }
This seems a little more reliable for me, because it will work even if the animation was not completed by the time the resize button was clicked.