删除故事板但保持动画价值?
-
18-09-2019 - |
题
如何在XAML中删除故事板(即DataTrigger中的removestoryboard动作),但要保留动画的值。类似于 Animatable.BeginAnimation:
如果动画的Begintime为null,则将删除任何当前动画,并将保留该属性的当前值。
解决方案
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呼叫开始激活也会达到类似的效果。
虽然begintime = null的开始启动是的确,使其看起来好像是复制到本地的,但后来呼叫删除值将导致值恢复。这是因为begintime = null的开始激发导致先前的动画保持其值,直到新动画的开始,但没有任何影响来影响本地值。
上面的代码实际上覆盖了本地值,因此所有动画都可以删除,并且对象仍然具有新值。因此,如果您真的想致电removestoryboard并仍然保留您的值,则需要我上面写的代码或类似的代码。
其他提示
我使用时也有类似的问题 AnimationTimeline
. 。最简单的解决方案正在捕获 Completed
在通话后面和之前的代码中发生的事件 BeginAnimation
与 null
参数要删除动画,获取属性的当前值并使用它来设置它。
这获得了最后一个动画值,并将其设置为。
void OnCompleted( object sender, EventArgs args )
{
// Required to copy latest animated value to local value.
o.SomeValue = o.SomeValue;
o.BeginAnimation( SomeClass.SomeValueProperty, null );
}