The problem

Sometimes you need to animate your specific object and for this purpose there is the WPF animation.

Here are the prerequireds :

  • The property you want to animate must be a DependencyProperty,
  • The property must so be a part of a DependencyObject,
  • Your object must implement IAnimatable to be able to launch the animation.


The difficulty resides in being able to create an animation, create a storyboard and set the corrects values for the attached properties - TargetName and TargetProperty - on the animation. All of this directly in the code.

You can then control the animation, the usual way than in XAML.

My solution/checklist

Here is how I did it, step by step.

First I make my business object derives from FrameWorkElement. Why ?
Because, this make my object a dependency object. Also, my object will implements IAnimatable ( FrameWorkElement heritate from UIElement which implements IAnimatable). And finally, it gets a NameScope which will be used later.
So here is my object:

public class Puppet: FrameworkElement {    }



Next I will had a DependencyProperty to be animated. Here I animate a value of type Point. I create all the usual things for the dependencyProperty and also add a storyboard (I will always use the same):

public class Puppet: FrameworkElement
{
   public static DependencyProperty ContactMovementProperty =
   DependencyProperty.Register("ContactMovement", typeof(Point), typeof(Puppet));
 
   public Point ContactMovement
   {
       get { return (Point)GetValue(SatelliteNavigator.ContactMovementProperty); }
       set { SetValue(SatelliteNavigator.ContactMovementProperty, value); }
    }
 
    private Storyboard stboard = new Storyboard();
}



Then, let's say I will create and launch the animation directly in the constructor. Here is the code added :

public class()
{
   //Maybe it was running before (if not set in the constructor)
   //stboard.Stop();
 
    double xFinal = 36;
    double yFinal = 36;
    PointAnimation animation = new PointAnimation();
 
    animation.From = ContactMovement;
    animation.To = new Point(xFinal , yFinal );
    animation.Duration = TimeSpan.FromMilliseconds(e.Velocity.Length*7 / deceleration);
    animation.AccelerationRatio = 0f;
    animation.DecelerationRatio = 0.4f;
    String puppetName= "puppet";
 
    NameScope nams = new NameScope();
    NameScope.SetNameScope(this, nams);
    this.RegisterName(puppetName, this);
 
    Storyboard.SetTargetName(animation, puppetName);
    Storyboard.SetTargetProperty(animation, new PropertyPath(Puppet.ContactMovementProperty));
 
    stboard.Children.Add(animation);
    stboard.Begin(this);
 
}


What is done ? First I create the animation with random values for our example.
Then I create a NameScope and set it to our object. Why ? Because it's not created by the runtime for our object and we need one. It will be used by the animation to retrieve the object to animate.

This is done by registering the Puppet object in the namescope and giving the same TargetName of the attachedProperty of the animation(Storyboard.SetTargetName).

Then we clear the children animation of the storyboard (maybe it was not empty) and launch the storyboard by giving it the Puppet (object in which the animated object is).



We can then use the usual methods on storyboard to control the play of the media. For example :

stboard.Stop();


Conclusion

As you can see this is not as easy as writing some XAML lines but it's not impossible !

Any questions ?

kick it on DotNetKicks.com


Shout it