1

我正在尝试实现一个自定义IEasingFunction,它基本上是另一个的包装器,IEasingFunction但它在动画的开头和结尾添加了一个暂停。我不希望它继承,EasingFunctionBase因为在 PausingEasingFunction 上有一个 EasingMode 是没有意义的。无论您使用哪种模式,暂停都是相同的,并且被包装的模式可以自行指定其模式。

这是它的外观:PausingEasingFunction.cs

public class PausingEasingFunction : DependencyObject, IEasingFunction
{
    public static readonly DependencyProperty WrappedEasingFunctionProperty = DependencyProperty.Register(nameof(WrappedEasingFunction), typeof(IEasingFunction), typeof(PausingEasingFunction));

    public static readonly DependencyProperty StartPauseProperty = DependencyProperty.Register(nameof(StartPause), typeof(double), typeof(PausingEasingFunction));

    public static readonly DependencyProperty EndPauseProperty = DependencyProperty.Register(nameof(EndPause), typeof(double), typeof(PausingEasingFunction));

    public IEasingFunction WrappedEasingFunction
    {
        get => (IEasingFunction)GetValue(WrappedEasingFunctionProperty);
        set => SetValue(WrappedEasingFunctionProperty, value);
    }

    public double StartPause
    {
        get => (double)GetValue(StartPauseProperty);
        set => SetValue(StartPauseProperty, value);
    }

    public double EndPause
    {
        get => (double)GetValue(EndPauseProperty);
        set => SetValue(EndPauseProperty, value);
    }

    public double Ease(double normalizedTime)
    {
        if (normalizedTime < StartPause)
        {
            return 0;
        }
        else if (normalizedTime <= 1 - EndPause)
        {
            if (WrappedEasingFunction == null)
            {
                return (normalizedTime - StartPause) / (1 - StartPause - EndPause);
            }
            else
            {
                return WrappedEasingFunction.Ease((normalizedTime - StartPause) / (1 - StartPause - EndPause));
            }
        }
        else
        {
            return 1;
        }
    }
}

问题是,当我尝试使用以下 xaml 在动画中使用它时(local:指的是 xmlns 指向包含的 clr 命名空间PausingEasingFunction):

<TextBlock Text="Hello I am some animated text!">
    <TextBlock.RenderTransform>
        <TranslateTransform X="0" x:Name="transform"/>
    </TextBlock.RenderTransform>
    <TextBlock.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <BeginStoryboard.Storyboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="X" Storyboard.TargetName="transform" RepeatBehavior="Forever" From="0" To="100" Duration="0:0:10">
                            <DoubleAnimation.EasingFunction>
                                <local:PausingEasingFunction>
                                    <local:PausingEasingFunction.WrappedEasingFunction>
                                        <SineEase EasingMode="EaseInOut"/>
                                    </local:PausingEasingFunction.WrappedEasingFunction>
                                </local:PausingEasingFunction>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard.Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </TextBlock.Triggers>
</TextBlock>

抛出 InvalidOperationException,告诉我无法冻结 Freezable。但是,如果我将PausingEasingFunction.cs更改为继承,Freezable而不是通过DependencyObject这种方式实现 CreateInstanceCore:

protected override Freezable CreateInstanceCore()
{
    return new PausingEasingFunction();
}

不再抛出异常。经过一番调查,我发现 WPF 仍然试图冻结东西,即使它们有 CanFreeze = false 但我不确定这是否真的是问题所在......

这是一个WPF错误吗?难道我做错了什么?或者为什么我被迫从 Freezable 继承?

4

0 回答 0