当动画完成或取消时,如何将动画的最终值设置为属性?

发布于 2024-07-14 08:55:55 字数 1135 浏览 6 评论 0原文

我尝试将 DependencyProperty 从一个值设置为目标值(在代码中),并在动画完成(或取消)时将最终值设置为该属性。 如果动画完成,最终值将是“To”值;如果动画取消,则最终值将是“当前”计算值(由动画计算)。

默认情况下,动画没有此行为,并且动画即使已完成也不会更改实际值。

失败的尝试

不久前,我编写了这个辅助方法来实现上述行为:

static void AnimateWithAutoRemoveAnimationAndSetFinalValue(IAnimatable element,
    DependencyProperty property,
    AnimationTimeline animation)
{
    var obj = element as DependencyObject;
    if (obj == null)
        throw new ArgumentException("element must be of type DependencyObject");
    EventHandler handler = null;
    handler = (sender, e) =>
    {
        var finalValue = obj.GetValue(property);
        //remove the animation
        element.BeginAnimation(property, null);
        //reset the final value
        obj.SetValue(property, finalValue);

        animation.Completed -= handler;

    };

    animation.Completed += handler;

    element.BeginAnimation(property, animation);
}

不幸的是,如果有人调用 BeginAnimation(property,null) 删除动画,则 Completed 事件似乎不会触发,因此取消动画时,我无法正确设置最终值。 更糟糕的是我也无法删除事件处理程序...

有人知道如何以干净的方式执行此操作吗?

I try to animate a DependencyProperty from a value to a target value (in code) and when the animation finishes (or is canceled) set the final value to the property. The final value would be either the To value if the animation finishes or the current computed value (by the animation) when the animation is canceled.

By default the Animation doesn't have this behavior and an Animation doesn't change the actual value even if it has completed.

A failed attempt

A while ago I wrote this helper method to achieve the mentioned behavior:

static void AnimateWithAutoRemoveAnimationAndSetFinalValue(IAnimatable element,
    DependencyProperty property,
    AnimationTimeline animation)
{
    var obj = element as DependencyObject;
    if (obj == null)
        throw new ArgumentException("element must be of type DependencyObject");
    EventHandler handler = null;
    handler = (sender, e) =>
    {
        var finalValue = obj.GetValue(property);
        //remove the animation
        element.BeginAnimation(property, null);
        //reset the final value
        obj.SetValue(property, finalValue);

        animation.Completed -= handler;

    };

    animation.Completed += handler;

    element.BeginAnimation(property, animation);
}

Unfortunately the Completed event doesn't seem to fire if the Animation is removed by someone calling BeginAnimation(property,null) and therefore I cannot set the final value correctly when an Animation is canceled. What is worse I cannot remove the event handler either...

Does someone know how to do this in a clean way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧人 2024-07-21 08:55:55

看起来您正在尝试在动画结束后将值设置回动画开始之前的初始值。 如果您停止动画(或动画时间线结束时),这实际上会自动发生。 在 WPF 中,动画可以被视为属性当前值之上的值叠加。 停止或删除动画将删除叠加层,之前的值现在将再次开始显示。 原来的价值并没有消失,只是暂时被掩盖了。

一般来说,将属性显式设置回其先前的值是不好的做法,因为如果该值最初不是在对象上本地设置的,则可能会产生内存开销。 此外,这可能会在以后带来一些微妙的问题。 例如,如果旧值是从样式派生的,则如果样式更改,该属性将不再更改。

如果您仍然觉得必须提取当前值并稍后恢复它,请使用 ReadLocalValue() 而不是 GetValue()。 如果该值未在本地设置,这将返回 DepenencyProperty.UnsetValue。 然后,您可以有条件地调用 ClearValue() 或 SetValue(),具体取决于该属性最初是否具有本地值。

It looks like you are trying to set value back to the initial value prior to the animation starts just after the animation finishes. This actually happens automatically if you stop the animation (or when the animation timeline finishes). Animations, in WPF, can be though of as an value overlay on top of the current value of the property. Stopping or removing an animation will remove the overlay and the prior value will now start showing through again. The original value is not lost, it is being temporarily obscured.

Setting the property explicitly back to its prior value is, in general, bad practice because it can incur a memory overhead if the value was not originally set locally on the object. Also, this can introduce subtle problems later. For example, if the old value was derived from a style, the property will no longer change if the style changes.

If you still feel you must extract the current value and later restore it, use ReadLocalValue() instead of GetValue(). This will return DepenencyProperty.UnsetValue if the value is not set locally. You can then conditionally call ClearValue() or SetValue() depending on whether the property initially had a local value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文