GridSplitter does not work after applying animation to a grid column

I am new to wpf, today I am facing an odd problem that gridsplitter stops working if I add animation to the grid column, below is a code snippet, this is a meaningless but fairly simple test code, it does nothing except the mouse enters right column, its width will increase from 15 to 100

<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Name="c1"/> <ColumnDefinition Name="c2" Width="15" MinWidth="15"/> </Grid.ColumnDefinitions> <Border Grid.Column="0" Background="Gray"></Border> <GridSplitter Width="8" Background="Yellow"></GridSplitter> <Border Grid.Column="1" Background="Silver" Name="bdRight" MouseEnter="bdRight_MouseEnter"></Border> </Grid> 

and this:

  bool flag = true; private void bdRight_MouseEnter(object sender, MouseEventArgs e) { if (flag) { flag = false; var da = new GridLengthAnimation(); da.From = new GridLength(c2.MinWidth); da.To = new GridLength(100); var ef = new BounceEase(); ef.EasingMode = EasingMode.EaseOut; da.EasingFunction = ef; this.c2.BeginAnimation(ColumnDefinition.WidthProperty, da); } } 

and here is GridLengthAnimation, I get it from the Internet after I find that DoubleAnimation cannot be used against the width of the grid column.

 public class GridLengthAnimation : AnimationTimeline { public static readonly DependencyProperty FromProperty; public static readonly DependencyProperty ToProperty; public static readonly DependencyProperty EasingFunctionProperty; static GridLengthAnimation() { FromProperty = DependencyProperty.Register("From", typeof(GridLength), typeof(GridLengthAnimation)); ToProperty = DependencyProperty.Register("To", typeof(GridLength), typeof(GridLengthAnimation)); EasingFunctionProperty = DependencyProperty.Register("EasingFunction", typeof(IEasingFunction), typeof(GridLengthAnimation)); } protected override Freezable CreateInstanceCore() { return new GridLengthAnimation(); } public override Type TargetPropertyType { get { return typeof(GridLength); } } public IEasingFunction EasingFunction { get { return (IEasingFunction)GetValue(GridLengthAnimation.EasingFunctionProperty); } set { SetValue(GridLengthAnimation.EasingFunctionProperty, value); } } public GridLength From { get { return (GridLength)GetValue(GridLengthAnimation.FromProperty); } set { SetValue(GridLengthAnimation.FromProperty, value); } } public GridLength To { get { return (GridLength)GetValue(GridLengthAnimation.ToProperty); } set { SetValue(GridLengthAnimation.ToProperty, value); } } public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock) { double fromValue = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value; double toValue = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value; IEasingFunction easingFunction = this.EasingFunction; double progress = (easingFunction != null) ? easingFunction.Ease(animationClock.CurrentProgress.Value) : animationClock.CurrentProgress.Value; if (fromValue > toValue) { return new GridLength((1 - progress) * (fromValue - toValue) + toValue, this.To.IsStar ? GridUnitType.Star : GridUnitType.Pixel); } else { return new GridLength((progress) * (toValue - fromValue) + fromValue, this.To.IsStar ? GridUnitType.Star : GridUnitType.Pixel); } } } 

If I comment on the codes in the MouseEnter event handler, the splitter works fine, otherwise it stops working. Any ideas?

+6
source share
2 answers

You must set the FillBehavior property of your animation. The default value is HoldEnd , which means that the animation saves the final value after it ends. If you set FillBehavior to Stop , the animated value will revert to the value that was before the animation.

If you add the following lines to the event handler code, it should work as expected:

 ... da.FillBehavior = FillBehavior.Stop; c2.Width = da.To; // set final value before starting the animation c2.BeginAnimation(ColumnDefinition.WidthProperty, da); 

If you set the final value before starting the animation creates a flickering effect, you can instead set the final value in the Completed handler:

 ... da.FillBehavior = FillBehavior.Stop; da.Completed += (s, e) => c2.Width = da.To; c2.BeginAnimation(ColumnDefinition.WidthProperty, da); 
+8
source

Just to expand the earlier answer (will comment, but not allowed by the stackoverflow supermaster):

For me, setting the final value before starting the animation, you get an ugly flicker effect for my grid a second before the animation.

What I did was use the FillBehavior.Stop mentioned above, but subscribe to the Animation.Completed event and set the final height of the grid column there.

Works like a charm without any flicker.

+1
source

Source: https://habr.com/ru/post/908871/


All Articles