This topic describes how and when to extend the WPF animation system by creating custom key frames, animation classes, or by using per-frame callback to bypass it.
To understand this topic, you should be familiar with the different types of animations provided by the WPF. For more information, see the From/To/By Animations Overview, the Key-Frame Animations Overview, and the Path Animations Overview.
Because the animation classes inherit from the Freezable class, you should be familiar with Freezable objects and how to inherit from Freezable. For more information, see the Freezable Objects Overview.
Extending the Animation System
There are a number of ways to extend the WPF animation system, depending on the level of built-in functionality you want to use. There are three primary extensibility points in the WPF animation engine:
Create a custom key frame object by inheriting from one of the <Type>KeyFrame classes, such as DoubleKeyFrame. This approach uses most of the built-in functionality of the WPF animation engine.
Create your own animation class by inheriting from AnimationTimeline or one of the <Type>AnimationBase classes.
Use per-frame callback to generate animations on a per-frame basis. This approach completely bypasses the animation and timing system.
The following table describes some the scenarios for extending the animation system.
|When you want to...||Use this approach|
|Customize the interpolation between values of a type that has a corresponding <Type>AnimationUsingKeyFrames||Create a custom key frame. For more information, see the Create a Custom Key Frame section.|
|Customize more than just the interpolation between values of a type that has a corresponding <Type>Animation.||Create a custom animation class that inherits from the <Type>AnimationBase class that corresponds to the type you want to animate. For more information, see the Create a Custom Animation Class section.|
|Animate a type that has no corresponding WPF animation||Use an ObjectAnimationUsingKeyFrames or create a class that inherits from AnimationTimeline. For more information, see the Create a Custom Animation Class section.|
|Animate multiple objects with values that are computed each frame and are based on the last set of object interactions||Use per-frame callback. For more information, see the Create a Use Per-Frame Callback section.|
Create a Custom Key Frame
Creating a custom key frame class is the simplest way to extend the animation system. Use this approach when you want to a different interpolation method for a key-frame animation. As described in the Key-Frame Animations Overview, a key-frame animation uses key frame objects to generate its output values. Each key frame object performs three functions:
Specifies a target value using its Value property.
Specifies the time at which that value should be reached using its KeyTime property.
Interpolates between the value of the previous key frame and its own value by implementing the InterpolateValueCore method.
Derive from the <Type>KeyFrame abstract class and implement the InterpolateValueCore method. The InterpolateValueCore method returns the current value of the key frame. It takes two parameters: the value of the previous key frame and a progress value that ranges from 0 to 1. A progress of 0 indicates the key frame has just started, and a value of 1 indicates that the key frame has just completed and should return the value specified by its Value property.
Because the <Type>KeyFrame classes inherit from the Freezable class, you must also override CreateInstanceCore core to return a new instance of your class. If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.
After you've created your custom <Type>KeyFrame animation, you can use it with the <Type>AnimationUsingKeyFrames for that type.
Create a Custom Animation Class
Creating your own animation type gives you more control over how an object in animated. There are two recommended ways to create your own animation type: you can derive from the AnimationTimeline class or the <Type>AnimationBase class. Deriving from the <Type>Animation or <Type>AnimationUsingKeyFrames classes is not recommended.
Derive from <Type>AnimationBase
Deriving from a <Type>AnimationBase class is the simplest way to create a new animation type. Use this approach when you want to create a new animation for type that already has a corresponding <Type>AnimationBase class.
Derive from a <Type>Animation class and implement the GetCurrentValueCore method. The GetCurrentValueCore method returns the current value of the animation. It takes three parameters: a suggested starting value, a suggested ending value, and an AnimationClock, which you use to determine the progress of the animation.
Because the <Type>AnimationBase classes inherit from the Freezable class, you must also override CreateInstanceCore core to return a new instance of your class. If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.
For more information, see the GetCurrentValueCore method documentation for the <Type>AnimationBase class for the type that you want to animate. For an example, see the Custom Animation Sample
If you simply want to change how animation values are interpolated, considering deriving from one of the <Type>KeyFrame classes. The key frame you create can be used with the corresponding <Type>AnimationUsingKeyFrames provided by WPF.
Derive from AnimationTimeline
Derive from the AnimationTimeline class when you want to create an animation for a type that doesn't already have a matching WPF animation, or you want to create an animation that is not strongly typed.
Derive from the AnimationTimeline class and override the following members:
GetCurrentValue – Override this method to return the current value of your animation. It takes three parameters: a default origin value, a default destination value, and an AnimationClock. Use the AnimationClock to obtain the current time or progress for the animation. You can choose whether to use the default origin and destination values.
If the class does not use dependency properties to store its data or it requires extra initialization after creation, you might need to override additional methods; see the Freezable Objects Overview for more information.
The recommended paradigm (used by WPF animations) is to use two inheritance levels:
Create an abstract <Type>AnimationBase class that derives from AnimationTimeline. This class should override the TargetPropertyType method. It should also introduce a new abstract method, GetCurrentValueCore, and override GetCurrentValue so that it validates the types of the default origin value and default destination value parameters, then calls GetCurrentValueCore.
Create another class that inherits from your new <Type>AnimationBase class and overrides the CreateInstanceCore method, the GetCurrentValueCore method that you introduced, and the IsDestinationDefault property.
If you want to animate a type that has no corresponding From/To/By animation or key-frame animation, consider using an ObjectAnimationUsingKeyFrames. Because it is weakly typed, an ObjectAnimationUsingKeyFrames can animate any type of value. The drawback to this approach is that ObjectAnimationUsingKeyFrames only supports discrete interpolation.
Use Per-Frame Callback
Use this approach when you need to completely bypass the WPF animation system. One scenario for this approach is physics animations, where at each animation step a new direction or position of animated objects needs to be recomputed based on the last set of object interactions.
Unlike the other approaches described in this overview, to use per-frame callback you don't need to create a custom animation or key frame class.
Instead, you register for the Rendering event of the object that contains the objects you want to animate. This event handler method gets called once per frame. Each time that WPF marshals the persisted rendering data in the visual tree across to the composition tree, your event handler method is called.
In your event handler, perform your whatever calculations necessary for your animation effect and set the properties of the objects you want to animate with these values.
To obtain the presentation time of the current frame, the EventArgs associated with this event can be cast as RenderingEventArgs, which provide a RenderingTime property that you can use to obtain the current frame's rendering time.
For more information, see the Rendering page.
Property Animation Techniques Overview
Freezable Objects Overview
Key-Frame Animations Overview
Path Animations Overview
Animation and Timing System Overview
Custom Animation Sample