kirupa.com - Modifying Animations using C#: Page 5

       by kirupa  |  14 May 2008 In the previous page, we drilled through our XAML using C#, found the elusive KeyTime property, and set its value depending on what our incrementer value was. Yet, when you ran the animation, nothing happened. What gives? The heading should give it away on why even though you changed your KeyTime property's values, your animation's speed did not change. The reason is that properties of a running animation cannot be changed without you restarting the animation. That means that any changes you make get queued, and when you restart your animation, those changes get applied. This means that you will need to add one more line of code: private void ModifyAnimation(double incrementer) { Storyboard sb = this.FindResource("Oscillate") as Storyboard; DoubleAnimationUsingKeyFrames animation = sb.Children[0] as DoubleAnimationUsingKeyFrames; DoubleKeyFrameCollection keyFrames = animation.KeyFrames; for (int i = 0; i < keyFrames.Count; i++) { SplineDoubleKeyFrame keyFrame = keyFrames[i] as SplineDoubleKeyFrame; keyFrame.KeyTime = new TimeSpan(0, 0, (int)incrementer * i); } sb.Begin(this); } To restart your animation, you call the Begin method on your storyboard - which is sb in our case. If you were to run your application this time, notice that changing the speed values in your combobox changes the speed of the circle's oscillation. For this type of animation, you are bound to see the jump where the ball skips to its starting location whenever you change the speed and the animation restarts. You can work around that generally by setting a virtual keyframe at Time 0 where there is no keyframe that point: [ normally, setting a virtual keyframe is a good way to stop the jump ] The only problem is that this type of animation doesn't work well to virtual keyframes. There are many other types of animations that do work well, so you will have to experiment and figure out a way to prevent the jumping. There are more complicated programmatic ways of preventing the jump, but I will save the discussion of that topic for a later time. Your final code for Window1.xaml.cs should be as follows: public partial class Window1 { public Window1() { this.InitializeComponent();   // Insert code required on object creation below this point. }   private void ChangeSpeed(object sender, SelectionChangedEventArgs e) { double incrementer = 1;   ComboBox comboBox = sender as ComboBox; ComboBoxItem selectedItem = comboBox.SelectedValue as ComboBoxItem;   string speed = selectedItem.Content.ToString();   if (speed == "Slow") { incrementer = 3; } else if (speed == "Normal") { incrementer = 2; } else if (speed == "Fast") { incrementer = 1; }   ModifyAnimation(incrementer); }   private void ModifyAnimation(double incrementer) { Storyboard sb = this.FindResource("Oscillate") as Storyboard; DoubleAnimationUsingKeyFrames animation = sb.Children[0] as DoubleAnimationUsingKeyFrames; DoubleKeyFrameCollection keyFrames = animation.KeyFrames;   for (int i = 0; i < keyFrames.Count; i++) { SplineDoubleKeyFrame keyFrame = keyFrames[i] as SplineDoubleKeyFrame; keyFrame.KeyTime = new TimeSpan(0, 0, (int)incrementer * i); }   sb.Begin(this); } } And with that, you should be set! If you are curious to see how my implementation turned out, you can download the source final source files below: Hopefully, this tutorial gave you an appreciation of how working between XAML and C# can actually save you a lot of time. What is nice about this is that you take advantage of quickly creating the framework of your animation - either manually or using a tool such as Expression Blend, and then manipulating the parts that you can't change easily in XAML using C#. If you had to pick only C# or only XAML, the end result would be more difficult to achieve. The amount of C# code needed to, for example, define the TranslateTransform.X on your storyboard is not easy to figure out even with the XAML in front of you. Being able to change the KeyTime value based on a combobox selection change is quite difficult (if not impossible) to do using just XAML. At the very least, you will need to write some code to create a ValueConverter to translate the Slow, Fast, and Normal values to the corresponding incrementer values. If you have any questions related to what you saw in this tutorial or anything WPF, Silverlight, etc., please post in our Programming forum. Got a question or just want to chat? Comment below or drop by our forums (they are actually the same thing!) where a bunch of the friendliest people you'll ever run into will be happy to help you out! When Kirupa isn’t busy writing about himself in 3rd person, he is practicing social distancing…even on his Twitter, Facebook, and LinkedIn profiles. Hit Subscribe to get cool tips, tricks, selfies, and more personally hand-delivered to your inbox.  

This is a companion discussion topic for the original entry at https://www.kirupa.com/blend_wpf/modifying_animations_pg5.htm