Pertanyaan GridSplitter tidak berfungsi setelah menerapkan animasi ke kolom grid


Saya seorang pemula di wpf, hari ini saya menemukan masalah aneh bahwa gridsplitter berhenti bekerja jika saya menambahkan animasi ke kolom grid, di bawah ini adalah potongan kode, itu adalah kode pengujian yang tidak berarti tapi cukup sederhana, itu tidak melakukan apa-apa kecuali ketika mouse memasuki kolom kanan, lebarnya akan mengembang dari 15 hingga 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>

dan ini:

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

dan inilah GridLengthAnimation, saya mendapatkannya dari internet setelah saya menemukan bahwa DoubleAnimation tidak dapat digunakan terhadap lebar kolom grid.

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

Jika saya mengomentari kode di pengendali event MouseEnter, splitter berfungsi dengan baik, jika tidak, berhenti bekerja. Ada ide?


7
2018-02-20 08:22


asal


Jawaban:


Anda harus mengatur FillBehavior milik animasi Anda. Nilai standarnya adalah HoldEnd, yang berarti bahwa animasi memegang nilai akhir setelah itu berakhir. Jika Anda mengatur FillBehavior ke Stop nilai animasi akan kembali ke nilai sebelumnya sebelum animasi beeing.

Jika Anda menambahkan baris berikut ke kode event handler Anda, itu harus bekerja seperti yang diharapkan:

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

Jika pengaturan nilai akhir sebelum memulai animasi menciptakan efek kedip-kedip, Anda dapat menetapkan nilai akhir dalam a Completed handler:

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

10
2018-02-20 09:32



Hanya untuk memperluas jawaban sebelumnya (komentar akan tetapi tidak diizinkan oleh overmaster stackoverflow):

Bagi saya, pengaturan nilai akhir sebelum memulai animasi menghasilkan efek flicker buruk untuk grid saya sepersekian detik sebelum animasi dimulai.

Yang saya lakukan adalah menggunakan FillBehavior. Hentikan yang disebutkan di atas tetapi berlangganan ke Animation.Completed event dan atur tinggi akhir dari kolom grid di sana.

Bekerja seperti pesona tanpa berkedip.


1
2018-06-14 13:34