8

我是 wpf 的初学者,今天我遇到了一个奇怪的问题,如果我将动画添加到网格列,gridsplitter 就会停止工作,下面是代码片段,这是一个毫无意义但非常简单的测试代码,它什么也不做,除非当鼠标进入右栏,宽度会从15扩大到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>

还有这个:

        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);
        }
    }

这是GridLengthAnimation,我发现DoubleAnimation不能用于网格列的宽度后,我从互联网上得到它。

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);
        }
    }
}

如果我在 MouseEnter 事件处理程序中注释掉代码,则拆分器可以正常工作,否则它将停止工作。有任何想法吗?

4

2 回答 2

11

您必须设置动画的FillBehavior属性。默认值为HoldEnd,这意味着动画在结束后保持最终值。如果将 FillBehavior 设置Stop为动画值,将恢复为动画之前的值。

如果您将以下行添加到事件处理程序代码中,它应该可以按预期工作:

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

如果在开始动画之前设置最终值会产生闪烁效果,您可以改为在Completed处理程序中设置最终值:

...
da.FillBehavior = FillBehavior.Stop;
da.Completed += (s, e) => c2.Width = da.To;
c2.BeginAnimation(ColumnDefinition.WidthProperty, da);
于 2012-02-20T09:32:37.543 回答
1

只是为了扩展较早的答案(会评论但stackoverflow overmaster不允许):

对我来说,在开始动画之前设置最终值会在动画开始前一瞬间为我的网格生成丑陋的闪烁效果。

我所做的是使用上面提到的 FillBehavior.Stop 但订阅 Animation.Completed 事件并在那里设置网格列的最终高度。

像魅力一样工作,没有任何闪烁。

于 2012-06-14T13:34:14.773 回答