Вопрос по .net, wpf, xaml, animation – Ширина анимации к реальной ширине в WPF?

6

Как я могу анимировать ширину элемента от 0 до его фактической ширины в WPF?

Я попробовал это:

<ControlTemplate.Triggers>
    <EventTrigger RoutedEvent="Loaded">
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimation Duration="0:0:0.3" To="{Binding ElementName=MyElement, Path=ActualWidth}" From="0" Storyboard.TargetProperty="Width" Storyboard.TargetName="MyElement" />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</ControlTemplate.Triggers>

Если я изменю привязку на жестко закодированное значение, как100, то ширина правильно анимируется, за исключением того, что я хочу привязать к фактической ширине элемента.

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

Для записи, это тоже не работает:

To="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}"

Ваш Ответ

2   ответа
2

что привязки не могут быть использованы в анимации, является распространенной проблемой.

Один из обходных путей - использование вспомогательного объекта сSourceValue & TargetValue (которую вы можете привязать к чему угодно, включаяActualWidth) аCurrentValue (который возвращает анимированное значение) иProgress, который можно анимировать от 0,0 до 100,0. Когда прогресс меняется, вам просто нужно рассчитаCurrentValue с которой вы можете связатьWidth вашего объекта. Это не красиво, но должно работать.

@ PhillipScottGivens: ответ Энди всегда изменяет анимацию, создавая привязываемый слой поверх нее. То, что я предлагаю, отличается, я предлагаю промежуточный объект, который всегда использует ту же анимацию, которая оживляет егоProgress собственность от0 в100 (таким образом, анимация не изменяется), этот объект предоставляет значение анимации черезCurrentValue свойство, которое возвращает значение, рассчитанное по егоSourceValue, TargetValue а такжеProgress. H.B.
Я не совсем понимаю этот ответ. Не могли бы вы предоставить пример кода? Вы описываете что-то похожее на решение @ Энди? Phillip Scott Givens
10

что это так по многим причинам, и, пожалуйста, не стесняйтесь сообщить мне, сколько законов WPF я нарушил, но .. Я решил ту же проблему, создав собственную BindableDoubleAnimation.

public class BindableDoubleAnimation : DoubleAnimationBase
{
    DoubleAnimation internalAnimation;

    public DoubleAnimation InternalAnimation { get { return internalAnimation; } }

    public double To
    {
        get { return (double)GetValue(ToProperty); }
        set { SetValue(ToProperty, value); }
    }

    /// <summary>
    /// Dependency backing property for the <see cref="To"/> property.
    /// </summary>
    public static readonly DependencyProperty ToProperty =
        DependencyProperty.Register("To", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) =>
            {
                BindableDoubleAnimation sender = (BindableDoubleAnimation)s;
                sender.internalAnimation.To = (double)e.NewValue;
            })));


    public double From
    {
        get { return (double)GetValue(FromProperty); }
        set { SetValue(FromProperty, value); }
    }

    /// <summary>
    /// Dependency backing property for the <see cref="From"/> property.
    /// </summary>
    public static readonly DependencyProperty FromProperty =
        DependencyProperty.Register("From", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) =>
        {
            BindableDoubleAnimation sender = (BindableDoubleAnimation)s;
            sender.internalAnimation.From = (double)e.NewValue;
        })));


    public BindableDoubleAnimation()
    {
        internalAnimation = new DoubleAnimation();
    }

    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
    {
        return internalAnimation.GetCurrentValue(defaultOriginValue, defaultDestinationValue, animationClock);
    }

    protected override Freezable CreateInstanceCore()
    {
        return internalAnimation.Clone();;
    }
}

Теперь я могу свободно использовать привязки для свойств «От кого».

<local:BindableDoubleAnimation Storyboard.TargetProperty="Width" From="0" To="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Window}}"/>
Кто-нибудь заставил это работать наBindableDoubleAnimations, которые находятся внутриStoryboard то есть вVisualState изControlTemplate? Для случаев, когда у меня есть только одинBindableDoubleAnimation вVisualState и я жестко закодирую значение «Кому» (скажем, что-то вроде «100»), ничего не анимируется, и ниGetCurrentValueCore ниCreateInstanceCore звонят. В тех случаях, когда я использую привязку данных к свойству «To», привязка всегда завершается ошибкой, всегда выдается ошибка «Не удается найти источник для привязки ...». Даже когда я попробую все из вышеперечисленного дословно, это не получается. Jason Frank
... Я бы хотел, чтобы это сработало - похоже, это может быть отличным решением! Jason Frank

Похожие вопросы