GridLength Animation…
WPF Double animation is really nice yet sometime you need animation for GridLength…. Unfortunatly this is not supported in the WPF class library. yet here is the code to do this !!!
It is very simple all you have to do is to inherit from AnimationTimeline and overide the following methods
- TargetPropertyType
- CreateInstanceCore
- GetCurrentValue
Have a look at the code…. sometime C# is more meaningful then english
/// <summary>
/// Animates a grid length value just like the DoubleAnimation animates a double value
/// </summary>
public class GridLengthAnimation : AnimationTimeline
{
private bool isCompleted;
/// <summary>
/// Marks the animation as completed
/// </summary>
public bool IsCompleted
{
get { return isCompleted; }
set { isCompleted = value; }
}
/// <summary>
/// Sets the reverse value for the second animation
/// </summary>
public double ReverseValue
{
get { return (double)GetValue(ReverseValueProperty); }
set { SetValue(ReverseValueProperty, value); }
}
/// <summary>
/// Dependency property. Sets the reverse value for the second animation
/// </summary>
public static readonly DependencyProperty ReverseValueProperty =
DependencyProperty.Register(“ReverseValue”, typeof(double), typeof(GridLengthAnimation), new UIPropertyMetadata(0.0));
/// <summary>
/// Returns the type of object to animate
/// </summary>
public override Type TargetPropertyType
{
get
{
return typeof(GridLength);
}
}
/// <summary>
/// Creates an instance of the animation object
/// </summary>
/// <returns>Returns the instance of the GridLengthAnimation</returns>
protected override System.Windows.Freezable CreateInstanceCore()
{
return new GridLengthAnimation();
}
/// <summary>
/// Dependency property for the From property
/// </summary>
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(“From”, typeof(GridLength),
typeof(GridLengthAnimation));
/// <summary>
/// CLR Wrapper for the From depenendency property
/// </summary>
public GridLength From
{
get
{
return (GridLength)GetValue(GridLengthAnimation.FromProperty);
}
set
{
SetValue(GridLengthAnimation.FromProperty, value);
}
}
/// <summary>
/// Dependency property for the To property
/// </summary>
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(“To”, typeof(GridLength),
typeof(GridLengthAnimation));
/// <summary>
/// CLR Wrapper for the To property
/// </summary>
public GridLength To
{
get
{
return (GridLength)GetValue(GridLengthAnimation.ToProperty);
}
set
{
SetValue(GridLengthAnimation.ToProperty, value);
}
}
AnimationClock clock;
/// <summary>
/// registers to the completed event of the animation clock
/// </summary>
/// <param name=”clock”>the animation clock to notify completion status</param>
void VerifyAnimationCompletedStatus(AnimationClock clock)
{
if (this.clock == null)
{
this.clock = clock;
this.clock.Completed += new EventHandler(delegate(object sender, EventArgs e) { isCompleted = true; });
}
}
/// <summary>
/// Animates the grid let set
/// </summary>
/// <param name=”defaultOriginValue”>The original value to animate</param>
/// <param name=”defaultDestinationValue”>The final value</param>
/// <param name=”animationClock”>The animation clock (timer)</param>
/// <returns>Returns the new grid length to set</returns>
public override object GetCurrentValue(object defaultOriginValue,
object defaultDestinationValue, AnimationClock animationClock)
{
//check the animation clock event
VerifyAnimationCompletedStatus(animationClock);
//check if the animation was completed
if (isCompleted)
return (GridLength)defaultDestinationValue;
//if not then create the value to animate
double fromVal = this.From.Value;
double toVal = this.To.Value;
//check if the value is already collapsed
if (((GridLength)defaultOriginValue).Value == toVal)
{
fromVal = toVal;
toVal = this.ReverseValue;
}
else
//check to see if this is the last tick of the animation clock.
if (animationClock.CurrentProgress.Value == 1.0)
return To;
if (fromVal > toVal)
return new GridLength((1 – animationClock.CurrentProgress.Value) *
(fromVal – toVal) + toVal,
this.From.IsStar ? GridUnitType.Star : GridUnitType.Pixel);
else
return new GridLength(animationClock.CurrentProgress.Value *
(toVal – fromVal) + fromVal, this.From.IsStar ? GridUnitType.Star : GridUnitType.Pixel);
}
}
/// <summary>
/// Animates a double value
/// </summary>
public class ExpanderDoubleAnimation : DoubleAnimationBase
{
/// <summary>
/// Dependency property for the From property
/// </summary>
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(“From”, typeof(double?),
typeof(ExpanderDoubleAnimation));
/// <summary>
/// CLR Wrapper for the From depenendency property
/// </summary>
public double? From
{
get
{
return (double?)GetValue(ExpanderDoubleAnimation.FromProperty);
}
set
{
SetValue(ExpanderDoubleAnimation.FromProperty, value);
}
}
/// <summary>
/// Dependency property for the To property
/// </summary>
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(“To”, typeof(double?),
typeof(ExpanderDoubleAnimation));
/// <summary>
/// CLR Wrapper for the To property
/// </summary>
public double? To
{
get
{
return (double?)GetValue(ExpanderDoubleAnimation.ToProperty);
}
set
{
SetValue(ExpanderDoubleAnimation.ToProperty, value);
}
}
/// <summary>
/// Sets the reverse value for the second animation
/// </summary>
public double? ReverseValue
{
get { return (double)GetValue(ReverseValueProperty); }
set { SetValue(ReverseValueProperty, value); }
}
/// <summary>
/// Sets the reverse value for the second animation
/// </summary>
public static readonly DependencyProperty ReverseValueProperty =
DependencyProperty.Register(“ReverseValue”, typeof(double?), typeof(ExpanderDoubleAnimation), new UIPropertyMetadata(0.0));
/// <summary>
/// Creates an instance of the animation
/// </summary>
/// <returns></returns>
protected override Freezable CreateInstanceCore()
{
return new ExpanderDoubleAnimation();
}
/// <summary>
/// Animates the double value
/// </summary>
/// <param name=”defaultOriginValue”>The original value to animate</param>
/// <param name=”defaultDestinationValue”>The final value</param>
/// <param name=”animationClock”>The animation clock (timer)</param>
/// <returns>Returns the new double to set</returns>
protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
{
double fromVal = this.From.Value;
double toVal = this.To.Value;
if (defaultOriginValue == toVal)
{
fromVal = toVal;
toVal = this.ReverseValue.Value;
}
if (fromVal > toVal)
return (1 – animationClock.CurrentProgress.Value) *
(fromVal – toVal) + toVal;
else
return (animationClock.CurrentProgress.Value *
(toVal – fromVal) + fromVal);
}
}





Hello,
A question remark, if I do not set return value, and no autoreverse parameter, launching the animation twice make the gridLength parameter going from the “from” value to the “to” value, then invert the two value.
I think there might be usefull no to invert the value if no reverse parameter is defined ! (hors maybe defining the reverse value to the “to” value ??)
your idea ? conception ?
Okay.. reverse value is an addon feature… remove it…
That’s great! Many thanks
Nice one, worked a treat.
Thanks for sharing!
Hi,
how can i use it from code?
I can’t animate Grid.WidthProperty…. what is the right property?
Thank you! this was very helpful for me.