2009-11-05 31 views

Respuesta

4

El uso principal de RemoveStoryboard es eliminar los valores animados y restablecerlos a su estado no animado. En la mayoría de los casos, puede cambiar la llamada a PauseStoryboard o StopStoryboard en su lugar, dependiendo del caso específico. La única excepción es cuando necesita liberar recursos del guión gráfico o usarlos para otro propósito.

Si realmente desea eliminar el guión gráfico y mantener los valores de las propiedades, debe establecer los valores animados directamente en las propiedades. Esto se puede hacer mediante el establecimiento de cada valor con el valor de animación, algo como esto:

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)); 

    } 
} 

Llamada este derecho antes de quitar el guión gráfico para copiar los valores animados.

Editar Se ha comentado que este código puede ser innecesario porque llamar a BeginAnimation con BeginTime = null logra un efecto similar.

Si bien es cierto que BeginAnimation con BeginTime = null hace que parezca que los valores se copiaron en local, una llamada posterior a RemoveStoryboard hará que los valores se reviertan. Esto se debe a que BeginAnimation con BeginTime = null hace que la animación anterior mantenga sus valores pendientes del inicio de la nueva animación, pero no afecta en nada los valores locales.

El código anterior en realidad sobrescribe los valores locales, por lo que se pueden eliminar todas las animaciones y los objetos seguirán teniendo sus nuevos valores. Entonces, si realmente quiere llamar a RemoveStoryboard y aún conservar sus valores, necesitará el código que escribí arriba o algo similar.

+0

Como mencioné en mi pregunta, me gustaría hacerlo en XAML. El objetivo principal aquí es comenzar una nueva animación basada en un DataTrigger que comience con el valor actual. AFAIK como sé que no se puede lograr pausando o deteniendo el guión gráfico actual porque mantendría o restablecería el valor actual. También tenga en cuenta que su código no es necesario en WPF. Simplemente puede llamar a Animatable.BeginAnimation con una animación que tiene el BeginTime establecido en nulo. Tendrá el mismo efecto que el valor se copia a local. – bitbonk

+0

No estoy seguro de entender su necesidad. Si solo desea comenzar una nueva animación, ¿por qué no hacerlo sin llamar haciendo una acción EliminarAnimación en absoluto? WPF está diseñado para comenzar con los valores actuales en esa situación. ¿No está haciendo eso? –

+0

No es cierto que llamar a BeginAnimation con BeginTime = null tenga el mismo efecto que mi código. Específicamente, no copia los valores a local. Si llama a BeginAnimation con BeginTime = null y luego llama a RemoveAnimation, los valores volverán a ser originales porque los valores locales nunca se cambiaron.Pero si usa mi código, los valores se mantendrán porque en realidad se copian en local. Estaba explicando qué era necesario para que los valores locales se mantuvieran incluso después de RemoveAnimation, y el código como el que escribí ES necesario. ¿Tiene sentido? –

1

Tuve un problema similar al usar AnimationTimeline. La solución más fácil resultó capturar el evento Completed en el código anterior y antes de llamar al BeginAnimation con el parámetro null para eliminar la animación, obtener el valor actual de la propiedad y usarlo para configurarlo.

Esto obtiene el último valor animado y lo establece.

void OnCompleted(object sender, EventArgs args) 
{ 
    // Required to copy latest animated value to local value. 
    o.SomeValue = o.SomeValue; 
    o.BeginAnimation(SomeClass.SomeValueProperty, null); 
} 
Cuestiones relacionadas