2009-08-11 8 views
6

J'essaie d'utiliser l'animation WPF pour créer un effet où, lorsque les données d'une propriété de texte changent, le texte disparaît, puis revient ... ou de préférence un fondu enchaîné approprié .WPF Text Effet de fondu enchaîné

J'ai réussi la moitié de ce travail, le code ci-dessous répond à l'événement changé de texte, rend immédiatement le texte invisible puis l'aplanit en plus de 3 secondes.

Pour fondu de texte est aussi simple, je change juste les propriétés De et À de la balise. MAIS - le problème est que le texte sur l'écran change immédiatement. Cela est généralement absolument nécessaire, bien sûr, mais dans ce cas, je veux que le texte OLD disparaisse, puis le nouveau texte à fondre.

Y a-t-il un truc astucieux à faire dans l'animation WPF?

déclencheur actuel demi-fini:

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

Répondre

-1

Je ne pense pas que ce soit peut-être dans une solution XAML seule. Le TextBlock ne connaît pas le texte "ancien" et "nouveau", seulement le texte.

La façon dont je voudrais faire est de créer un contrôle personnalisé qui dérive de TextBlock, et procédez comme suit sur le TargetUpdated événement:

  • Appel « Fondu » story-board
  • du texte
  • 'Fondu' Appel storyboard

Bonne chance :)

+0

pour sûr est possible, il suffit d'utiliser deux blocs de texte – sam

1

La meilleure solution pour cette tâche serait d'utiliser un "Transition Presenter". Transition présentateur est un conteneur pour votre contrôle (peut être TextBlock ou autre) qui réagit à la modification du contenu en appliquant la transition affectée. Vous pouvez sélectionner l'une des transitions prédéfinies ou créer la vôtre (en utilisant XAML). Habituellement, le présentateur de transition utilise un modèle de données pour afficher les données liées. La plupart des exemple de base ressemblerait à ceci:

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

Voici deux bibliothèques avec le code source qui mettent en œuvre le présentateur de transition:

3

Je suis avec frances1983 sur ce. Ce que je ferais est de faire un nouveau UserControl qui gère réellement l'ancien et le nouveau texte de façon transparente avec les fondus.

Je fais quelque chose de similaire avec une étiquette que je veux seulement afficher pendant quelques secondes, puis disparaître. Voici ce que je l'ai fait:

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

Et puis dans le code où le texte change d'étiquette:

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

Vous pouvez modifier facilement cet échantillon dans un UserControl.Il suffit de changer le fondu sur la Visibilité == Caché, ajouter un storyboard qui fait le contraire pour la Visibilité == Visible, et changer le texte et réinitialiser la visibilité dans le gestionnaire de Tick.

Espérons que cela aide!

2

Voici une implémentation qui font automatiquement le fade-out, la valeur de commutation, fondu dans

Pour utiliser (après avoir réglé xmlns: l à l'espace de noms correct:

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

Le code (ce qui est code de preuve de concept, sans erreur de manipulation d'un prêt à la production n'est pas prêt)

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