【发布时间】:2010-12-13 15:20:34
【问题描述】:
如何在 XAML 中删除情节提要(即 DataTrigger 中的 RemoveStoryboard 操作)但保留动画的值。类似于Animatable.BeginAnimation:
如果动画的 BeginTime 为 null,则所有当前动画都将被移除并保留属性的当前值。
【问题讨论】:
标签: wpf animation storyboard datatrigger
如何在 XAML 中删除情节提要(即 DataTrigger 中的 RemoveStoryboard 操作)但保留动画的值。类似于Animatable.BeginAnimation:
如果动画的 BeginTime 为 null,则所有当前动画都将被移除并保留属性的当前值。
【问题讨论】:
标签: wpf animation storyboard datatrigger
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 并且仍然保留你的值,你将需要我上面写的代码或类似的东西。
【讨论】:
我在使用AnimationTimeline 时遇到了类似的问题。最简单的解决方案是在代码后面和之前使用 null 参数调用 BeginAnimation 之前在代码中捕获 Completed 事件以删除动画,获取属性的当前值并使用它来设置它。
这会获取最后一个动画值,并设置它。
void OnCompleted( object sender, EventArgs args )
{
// Required to copy latest animated value to local value.
o.SomeValue = o.SomeValue;
o.BeginAnimation( SomeClass.SomeValueProperty, null );
}
【讨论】: