1

IEasingFunction基本的に他のラッパーのカスタムを実装しようとしてIEasingFunctionいますが、アニメーションの最初と最後に一時停止が追加されます。EasingFunctionBasePausingEasingFunction に 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:を含む clr 名前空間を指す xmlns を参照します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代わりにDependencyObjectCreateInstanceCore を次のように実装するように変更すると、次のようになります。

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

例外はスローされなくなりました。調査の結果、CanFreeze = false であっても WPF がまだフリーズしようとしていることがわかりましたが、それが本当に問題なのかどうかはわかりません...

それはWPFのバグですか?私は何か間違ったことをしていますか?または、なぜ Freezable から継承せざるを得ないのですか?

4

0 に答える 0