2009-08-11 23 views
6

Estoy tratando de usar la animación WPF para crear un efecto donde, cuando los datos en una propiedad de texto cambian, el texto se desvanece, luego de nuevo ... o preferiblemente un crossfade adecuado .WPF Text Fade out-in-effect

He logrado que la mitad de esto funcione, el código siguiente responde al evento de cambio de texto, inmediatamente hace que el texto sea invisible y luego se desvanece en más de 3 segundos.

Para atenuar el texto, es igualmente simple, simplemente cambio las propiedades Desde y Hasta de la etiqueta. PERO - el problema es que el texto en la pantalla cambia inmediatamente. Esto es generalmente absolutamente necesario, por supuesto, pero en este caso quiero que el texto VIEJO se desvanezca, luego el texto NUEVO se desvanecerá.

¿Hay algún truco inteligente para hacer esto en la animación WPF?

actual a medio terminar de disparo:

<Style TargetType="TextBlock" x:Key="fadeinout"> 
     <Style.Triggers> 
      <EventTrigger RoutedEvent="Binding.TargetUpdated"> 
       <BeginStoryboard> 
        <Storyboard> 
         <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:3" From="0.0" To="1.0" BeginTime="0:0:0" /> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger> 
     </Style.Triggers> 
    </Style> 

Respuesta

-1

no creo que esto es posiblemente en una solución XAML-solamente. TextBlock no conoce el texto "antiguo" y el "nuevo", solo el texto.

La manera Me gustaría hacer esto es crear un control personalizado que deriva de TextBlock, y hacer lo siguiente en la TargetUpdated-evento:

  • llamada 'Fade out' Storyboard
  • Cambio texto
  • 'fade in'
  • Call guión gráfico

Buena suerte :)

+0

es seguro, solo use dos bloques de texto – sam

1

La mejor solución para esta tarea sería usar un "presentador de transición". Transition presentater es un contenedor para su control (puede ser TextBlock o lo que sea) que reacciona al cambio de contenido aplicando la transición asignada. Puede seleccionar una de las transiciones predefinidas o crear la suya propia (usando XAML). Por lo general, el presentador de transición usa una plantilla de datos para mostrar los datos encuadernados. La mayoría ejemplo básico sería el siguiente aspecto:

<lib:TransitionPresenter Transition="{StaticResource FadeTransition} 
    Content="{Binding MyValue}"> 
    <lib:TransitionPresenter.Resources> 
     <DataTemplate DataType="{x:Type System:string}"> 
      <TextBlock Text={Binding}/> 
     </DataTemplate> 
    </lib:TransitionPresenter.Resources> 
</lib:TransitionPresenter> 

Aquí hay dos bibliotecas con código fuente que implementan presentador de transición:

3

estoy con frances1983 en esta. Lo que haría sería crear un nuevo UserControl que realmente maneje el texto antiguo y el nuevo sin problemas con los fundidos.

Estoy haciendo algo similar con una etiqueta que quiero mostrar solo durante un par de segundos y luego desaparecer. Esto es lo que he hecho:

<Label Name="lbl" DockPanel.Dock="Bottom" HorizontalAlignment="Center" Visibility="Collapsed"> 
    <Label.Style> 
     <Style TargetType="{x:Type Label}"> 
      <Style.Triggers> 
       <Trigger Property="Visibility" Value="Visible"> 
        <Trigger.EnterActions> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="00:00:00" BeginTime="00:00:00" From="0.0" To="1.0" /> 
           <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="00:00:03" BeginTime="00:00:02" From="1.0" To="0.0" /> 
          </Storyboard> 
         </BeginStoryboard> 
        </Trigger.EnterActions> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </Label.Style> 
    Display Text 
</Label> 

Y luego en código donde los cambios en el texto de la etiqueta:

//Make the label visible, starting the storyboard. 
lbl.Visibility = Visibility.Visible; 

DispatcherTimer t = new DispatcherTimer(); 
//Set the timer interval to the length of the animation. 
t.Interval = new TimeSpan(0, 0, 5); 
t.Tick += (EventHandler)delegate(object snd, EventArgs ea) 
{ 
    // The animation will be over now, collapse the label. 
    lbl.Visibility = Visibility.Collapsed; 
    // Get rid of the timer. 
    ((DispatcherTimer)snd).Stop(); 
}; 
t.Start(); 

Usted podría modificar fácilmente esta muestra en un control de usuario.Simplemente cambie el fundido de salida en Visibilidad == Oculto, agregue un guión gráfico que haga lo contrario para Visibilidad == Visible, y cambie el texto y restablezca la visibilidad dentro del controlador Tick.

Espero que esto ayude!

2

Aquí es una aplicación que lo hacen automáticamente el fundido de salida, el valor del interruptor, se desvanecen en

Para utilizar (después de ajustar xmlns: l al espacio de nombres correcta:

Label l:AnimatedSwitch.Property="Content" l:AnimatedSwitch.Binding="{Binding SomeProp}"/> 

El código (esto es código de prueba de concepto, sin error, no está listo para la producción).

public class AnimatedSwitch : DependencyObject 
{ 
    // Define the attached properties 

    public static DependencyProperty BindingProperty = 
     DependencyProperty.RegisterAttached("Binding", typeof(object), typeof(AnimatedSwitch), 
     new PropertyMetadata(BindingChanged)); 
    public static DependencyProperty PropertyProperty = 
     DependencyProperty.RegisterAttached("Property", typeof(string), typeof(AnimatedSwitch)); 
    public static object GetBinding(DependencyObject e) 
    { 
     return e.GetValue(BindingProperty); 
    } 
    public static void SetBinding(DependencyObject e, object value) 
    { 
     e.SetValue(BindingProperty, value); 
    } 
    public static string GetProperty(DependencyObject e) 
    { 
     return (string)e.GetValue(PropertyProperty); 
    } 
    public static void SetProperty(DependencyObject e, string value) 
    { 
     e.SetValue(PropertyProperty, value); 
    } 

    // When the value changes do the fadeout-switch-fadein 

    private static void BindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     Storyboard fadeout = new Storyboard(); 
     var fadeoutAnim = new DoubleAnimation(){To=0,Duration=new Duration(TimeSpan.FromSeconds(0.3))}; 
     Storyboard.SetTarget(fadeoutAnim,d); 
     Storyboard.SetTargetProperty(fadeoutAnim, new PropertyPath("Opacity")); 
     fadeout.Children.Add(fadeoutAnim); 
     fadeout.Completed += (d1, d2) => 
      { 
       d.GetType().GetProperty(GetProperty(d)).SetValue(d, GetBinding(d), null); 

       Storyboard fadein = new Storyboard(); 
       var fadeinAnim = new DoubleAnimation() { To = 1, Duration = new Duration(TimeSpan.FromSeconds(0.3)) }; 
       Storyboard.SetTarget(fadeinAnim, d); 
       Storyboard.SetTargetProperty(fadeinAnim, new PropertyPath("Opacity")); 
       fadein.Children.Add(fadeinAnim); 
       fadein.Begin(); 
      }; 
     fadeout.Begin(); 
    } 
}