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:
を含む 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
代わりにDependencyObject
CreateInstanceCore を次のように実装するように変更すると、次のようになります。
protected override Freezable CreateInstanceCore()
{
return new PausingEasingFunction();
}
例外はスローされなくなりました。調査の結果、CanFreeze = false であっても WPF がまだフリーズしようとしていることがわかりましたが、それが本当に問題なのかどうかはわかりません...
それはWPFのバグですか?私は何か間違ったことをしていますか?または、なぜ Freezable から継承せざるを得ないのですか?