Customize GridLengthAnimation and wpfgridlength in WPF
Requirement
When editing an entry in a list, we want to place the edited details on the current side, such as the right side.
You can achieve this by dividing a Grid into two cloumns and dynamically adjusting the Width of the two cloumns.
We know that the Width of Clomun is A, but the default animation does not. We need to implement such a one-person animation by ourselves.
Design
We can see from the class diagram of Animation
We can
When editing an entry in a list, we want to place the edited details on the current side, such as the right side.
You can achieve this by dividing a Grid into two cloumns and dynamically adjusting the Width of the two cloumns.
We know that the Width of Clomun is GridLength, but the default animation does not. We need to implement such a one-person animation by ourselves.
Design
We can see from the class diagram of Animation that the AnimationTimeline inherits and overwrite its GetCurrentValue.
public class GridLengthAnimation : AnimationTimeline { /// <summary> /// Returns the type of object to animate /// </summary> public override Type TargetPropertyType => 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); } } /// <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) { double fromVal = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value; double toVal = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value; if (fromVal > toVal) return new GridLength((1 - animationClock.CurrentProgress.Value) * (fromVal - toVal) + toVal, GridUnitType.Star); else return new GridLength(animationClock.CurrentProgress.Value * (toVal - fromVal) + fromVal, GridUnitType.Star); }
As shown above, the default animation is used To implement From, To, and its attribute is defined as GridLength. When the animation is executed, we overwrite GetCurrentValue, associate it with the From/To attribute.
Optimization
With the above Code, we implement animation when GridLength changes. However, after the trial, we found that the animation is a bit too linear. What should I do at this time?
You can introduce EasingFunction. We know that EasingFunction is actually a time function f (t) related to time t. Through the processing of time functions, we make the animation transition not so linear.
/// <summary> /// The <see cref="EasingFunction" /> dependency property's name. /// </summary> public const string EasingFunctionPropertyName = "EasingFunction"; /// <summary> /// Gets or sets the value of the <see cref="EasingFunction" /> /// property. This is a dependency property. /// </summary> public IEasingFunction EasingFunction { get { return (IEasingFunction)GetValue(EasingFunctionProperty); } set { SetValue(EasingFunctionProperty, value); } } /// <summary> /// Identifies the <see cref="EasingFunction" /> dependency property. /// </summary> public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register( EasingFunctionPropertyName, typeof(IEasingFunction), typeof(GridLengthAnimation), new UIPropertyMetadata(null));
The GetCurrentValue function must be rewritten.
public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock) { double fromVal = ((GridLength)GetValue(FromProperty)).Value; double toVal = ((GridLength)GetValue(ToProperty)).Value; //check that from was set from the caller //if (fromVal == 1) // //set the from as the actual value // fromVal = ((GridLength)defaultDestinationValue).Value; double progress = animationClock.CurrentProgress.Value; IEasingFunction easingFunction = EasingFunction; if (easingFunction != null) { progress = easingFunction.Ease(progress); } if (fromVal > toVal) return new GridLength((1 - progress) * (fromVal - toVal) + toVal, GridUnitType.Star); return new GridLength(progress * (toVal - fromVal) + fromVal, GridUnitType.Star); }
Use
<anim:GridLengthAnimation Storyboard.TargetProperty="Width" From="0" To="*" Duration="0:0:0.5"/>
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.