8

私はwpfの初心者です。今日、グリッド列にアニメーションを追加するとグリッドスプリッターが機能しなくなるという奇妙な問題に遭遇しました。以下はコードスニペットです。これは無意味ですが、非常に単純なテストコードです。マウスが右の列に入ると、その幅が 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

以前の回答を拡張するだけです(コメントしますが、スタックオーバーフローのオーバーマスターでは許可されません):

私にとっては、アニメーションを開始する前に最終的な値を設定すると、アニメーションが開始される 1 秒前に、グリッドに醜いちらつき効果が生成されます。

私がしたことは、上記の FillBehavior.Stop を使用することでしたが、Animation.Completed イベントをサブスクライブし、そこにグリッド列の最終的な高さを設定しました。

ちらつきのない魔法のように機能します。

于 2012-06-14T13:34:14.773 に答える