2012-06-12 26 views
5

¿Cómo puedo animar el ancho de un elemento desde 0 hasta su ancho real en WPF?Ancho de animación al ancho real en WPF?

yo probamos este:

<ControlTemplate.Triggers> 
    <EventTrigger RoutedEvent="Loaded"> 
     <BeginStoryboard> 
      <Storyboard> 
       <DoubleAnimation Duration="0:0:0.3" To="{Binding ElementName=MyElement, Path=ActualWidth}" From="0" Storyboard.TargetProperty="Width" Storyboard.TargetName="MyElement" /> 
      </Storyboard> 
     </BeginStoryboard> 
    </EventTrigger> 
</ControlTemplate.Triggers> 

Si cambio la unión a un valor codificado, como 100, entonces el ancho está animado correctamente, salvo que yo quiero para unirse a la anchura real del elemento.

Si es importante, MyElement es un borde, y estoy animando un elemento de tabulación.

Para el registro, esto no funciona bien:

To="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}" 

Respuesta

9

Estoy seguro de que esto es incorrecto por MUCHOS motivos y no dude en decirme cuántas leyes de WPF violé, pero ... Resolví el mismo problema al crear mi propia Agilent Double Announcement.

public class BindableDoubleAnimation : DoubleAnimationBase 
{ 
    DoubleAnimation internalAnimation; 

    public DoubleAnimation InternalAnimation { get { return internalAnimation; } } 

    public double To 
    { 
     get { return (double)GetValue(ToProperty); } 
     set { SetValue(ToProperty, value); } 
    } 

    /// <summary> 
    /// Dependency backing property for the <see cref="To"/> property. 
    /// </summary> 
    public static readonly DependencyProperty ToProperty = 
     DependencyProperty.Register("To", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) => 
      { 
       BindableDoubleAnimation sender = (BindableDoubleAnimation)s; 
       sender.internalAnimation.To = (double)e.NewValue; 
      }))); 


    public double From 
    { 
     get { return (double)GetValue(FromProperty); } 
     set { SetValue(FromProperty, value); } 
    } 

    /// <summary> 
    /// Dependency backing property for the <see cref="From"/> property. 
    /// </summary> 
    public static readonly DependencyProperty FromProperty = 
     DependencyProperty.Register("From", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) => 
     { 
      BindableDoubleAnimation sender = (BindableDoubleAnimation)s; 
      sender.internalAnimation.From = (double)e.NewValue; 
     }))); 


    public BindableDoubleAnimation() 
    { 
     internalAnimation = new DoubleAnimation(); 
    } 

    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock) 
    { 
     return internalAnimation.GetCurrentValue(defaultOriginValue, defaultDestinationValue, animationClock); 
    } 

    protected override Freezable CreateInstanceCore() 
    { 
     return internalAnimation.Clone();; 
    } 
} 

Ahora soy libre de usar enlaces para las propiedades De.

<local:BindableDoubleAnimation Storyboard.TargetProperty="Width" From="0" To="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Window}}"/> 
+0

¿Alguien ha conseguido que esto funcione para 'BinbleDoubleAnimation's que están dentro de un' Storyboard' que está en 'VisualState' de' ControlTemplate'? Para los casos en que tengo solo un 'BindableDoubleAnimation' en' VisualState' y código de código para el valor "To" (para decir algo como "100"), nada se anima, y ​​ni 'GetCurrentValueCore' ni' CreateInstanceCore' se están llamando . En los casos en que utilizo el enlace de datos en la propiedad "Para", el enlace siempre falla, siempre generando el error "No se puede encontrar el origen del enlace ...". Incluso cuando pruebo todo textualmente desde arriba, falla. –

+0

... Me encantaría hacer que esto funcione, ¡parece que podría ser una gran solución! –

2

que las consolidaciones no se pueden utilizar en las animaciones es un problema común.

Una solución alternativa sería el uso de un objeto auxiliar que tiene SourceValue & TargetValue (que se puede enlazar con lo que quiera, incluyendo ActualWidth) un CurrentValue (que devuelve el valor de animación) y un Progress que puede ser animado de 0,0 a 100.0. Cuando se cambia el progreso, solo tiene que calcular CurrentValue al que puede enlazar el Width de su objeto. No es bonito, pero debería funcionar.

+0

No tengo claro esta respuesta. ¿Podría proporcionar una muestra de código? ¿Estás describiendo algo similar a la solución de @ Andy? –

+0

@PhillipScottGivens: la respuesta de Andy siempre modifica la animación creando una capa enlazable sobre ella. Lo que sugiero es diferente, sugiero un objeto intermediario que siempre usa la misma animación que anima su propiedad 'Progress' de' 0' a '100' (por lo tanto, la animación no cambia), este objeto proporciona el valor de la animación a través de' Propiedad CurrentValue' que devuelve el valor calculado a partir de su 'SourceValue',' TargetValue' y 'Progress'. –

Cuestiones relacionadas