GridSplitter не работает после применения анимации к столбцу сетки - PullRequest
8 голосов
/ 20 февраля 2012

Я новичок в 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, сплиттер работает нормально, в противном случае он перестает работать.Есть идеи?

Ответы [ 2 ]

11 голосов
/ 20 февраля 2012

Вы должны установить свойство 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);
1 голос
/ 14 июня 2012

Просто, чтобы расширить предыдущий ответ (будет комментировать, но не разрешено надстройщиком stackoverflow):

Для меня установка окончательного значения перед тем, как запустить анимацию, генерирует эффект мерзкого мерцания для моей сетки расколза секунду до начала анимации.

Что я сделал, так это использовал упомянутый выше FillBehavior.Stop, но подписался на событие Animation.Completed и установил там конечную высоту столбца сетки.

Работает как брелок без мерцания.

...