10

如何删除 XAML 中的情节提要(即 DataTrigger 中的 RemoveStoryboard 操作)但保留动画的值。类似于Animatable.BeginAnimation

如果动画的 BeginTime 为 null,则所有当前动画都将被移除并保留属性的当前值。

4

2 回答 2

4

RemoveStoryboard 的主要用途是删除动画值并将它们设置回其未动画状态。在大多数情况下,您可以将调用切换到 PauseStoryboard 或 StopStoryboard,具体取决于具体情况。唯一的例外是当您需要释放情节提要所持有的资源或将其用于其他目的时。

如果你真的想移除情节提要并保留属性值,你必须直接在属性上设置动画值。这可以通过将每个值设置为动画值来完成,如下所示:

void CopyAnimatedValuesToLocalValues(DependencyObject obj)
{
  // Recurse down tree
  for(int i=0; i<VisualTreeHelper.GetChildrenCount(obj); i++)
    CopyAnimatedValuesToLocalValues(VisualTreeHelper.GetChild(obj, i));

  var enumerator = obj.GetLocalValueEnumerator();
  while(enumerator.MoveNext())
  {
    var prop = enumerator.Current.Property;
    var value = enumerator.Current.Value as Freezable;

    // Recurse into eg. brushes that may be set by storyboard, as long as they aren't frozen
    if(value!=null && !value.IsFrozen)
      CopyAnimatedValuesToLocalValues(value);

    // *** This is the key bit of code ***
    if(DependencyPropertyHelper.GetValueSource(obj, prop).IsAnimated)
      obj.SetValue(prop, obj.GetValue(prop));

  }
}

在删除故事板以复制动画值之前调用它。

编辑有评论指出此代码可能是不必要的,因为使用 BeginTime=null 调用 BeginAnimation 可以达到类似的效果。

虽然 BeginTime=null 的 BeginAnimation 确实使值看起来像是复制到本地,但稍后调用 RemoveStoryboard 将导致值恢复。这是因为 BeginTime=null 的 BeginAnimation 会导致先前的动画在新动画开始之前保持其值,但不会影响本地值。

上面的代码实际上覆盖了本地值,所以所有的动画都可以被移除并且对象仍然有它们的新值。因此,如果您真的想调用 RemoveStoryboard 并仍然保留您的值,您将需要我在上面编写的代码或类似的代码。

于 2009-11-06T04:13:29.397 回答
1

我在使用时遇到了类似的问题AnimationTimeline。最简单的解决方案是Completed在代码中捕获事件,然后在使用参数调用以删除动画之前BeginAnimationnull获取属性的当前值并使用它来设置它。

这将获取最后一个动画值,并设置它。

void OnCompleted( object sender, EventArgs args )
{
    // Required to copy latest animated value to local value.
    o.SomeValue = o.SomeValue;
    o.BeginAnimation( SomeClass.SomeValueProperty, null );
}
于 2012-04-23T01:14:40.987 回答