删除故事板但保持动画值?

bit*_*onk 10 wpf animation datatrigger storyboard

如何在XAML中删除故事板(即DataTrigger中的RemoveStoryboard操作),但保留动画的值.与Animatable.BeginAnimation类似:

如果动画的BeginTime为null,则将删除任何当前动画,并保留属性的当前值.

Ray*_*rns 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));

  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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