2010-11-30 4 views
15

Dans mon application WPF, j'ai un contrôle de retour que je souhaite voir apparaître après la fin d'une action de l'utilisateur (sauvegarde des données, suppression ...). La visibilité est définie sur Hidden pour commencer et le style est défini sur le style animateFadeOut défini en tant que ressource (voir ci-dessous). Ensuite, je veux placer le texte et contrôler la visibilité visible dans mon code C# et avoir le contrôle de rétroaction afficher le message et disparaître après 5 secondes et rester caché (Visibility.Hidden).WPF Fade Out sur un contrôle

Le code XAML suivant fonctionne la première fois que j'appelle control.Visiblity = Visibility.Visible mais le contrôle ne réapparaît pas la deuxième fois. Je pense que c'est parce que l'animation est toujours en cours d'exécution, ce qui a le contrôle sur le contrôle de rétroaction. J'ai alors essayé de mettre FillBehavior à "Stop" mais cela a juste rendu le contrôle encore visible et je le veux caché. Puis, avec FillBehavior = "Stop", j'ai essayé de définir un trigger "quand Opacity = 0, place la Visibilité à Caché". Le déclencheur n'a pas semblé tirer et j'ai été laissé avec le contrôle visible une fois de plus après l'animation terminée.

S'il vous plaît aider à souligner ce que je fais mal ici. Alternativement, si vous pouvez suggérer un meilleur moyen d'afficher un contrôle qui disparaît après 5 secondes et peut être appelé encore et encore, j'apprécierais.

Merci!

<Style TargetType="{x:Type FrameworkElement}" x:Key="animateFadeOut"> 
     <Style.Triggers> 
      <Trigger Property="Visibility" Value="Visible"> 
       <Trigger.EnterActions> 
        <BeginStoryboard > 
         <Storyboard> 
          <DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity" 
         From="1.0" To="0.0" Duration="0:0:0.5"/> 
         </Storyboard> 
        </BeginStoryboard>    
       </Trigger.EnterActions> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
+0

Je pris une approche légèrement différente pour résoudre le problème ... Je l'ai écrit en C#. (Voir l'article ci-dessous - la section des commentaires est trop petite pour les messages de code) – sondlerd

Répondre

28

Le problème est que, après l'animation complète votre contrôle a toujours Visibilité = visible, ne peut donc pas être entré à nouveau.
Je préfère utiliser une animation qui fait tout, montre d'abord le contrôle, puis le cache.

<Storyboard x:Key="animate"> 
    <ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility"> 
     <DiscreteObjectKeyFrame KeyTime="0"> 
      <DiscreteObjectKeyFrame.Value> 
       <Visibility>Visible</Visibility> 
      </DiscreteObjectKeyFrame.Value> 
     </DiscreteObjectKeyFrame> 
    </ObjectAnimationUsingKeyFrames> 
    <DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.2"/> 
    <DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:0.5"/> 
    <ObjectAnimationUsingKeyFrames BeginTime="0:0:5.5" Storyboard.TargetProperty="Visibility"> 
     <DiscreteObjectKeyFrame KeyTime="0"> 
      <DiscreteObjectKeyFrame.Value> 
       <Visibility>Hidden</Visibility> 
      </DiscreteObjectKeyFrame.Value> 
     </DiscreteObjectKeyFrame> 
    </ObjectAnimationUsingKeyFrames> 
</Storyboard> 

et l'utiliser comme suit:

((Storyboard)FindResource("animate")).Begin(someControl); 
+0

merci, Alpha-Mouse. Vous avez répondu à la question que j'ai posté ci-dessous à Liz. Une autre question, une fois l'animation terminée, fait l'opacité = 0.0 ou est-ce seulement dans l'animation? Je demande parce que quand j'ai placé le FillBehavior à l'arrêt, l'opacité est revenue à 1.0. – sondlerd

+0

@sondlerd: lorsque FillBehaviour est Stop, alors oui, [la valeur de la propriété retourne à sa valeur d'origine] (http://msdn.microsoft.com/en-us/library/system.windows.media.animation.fillbehavior. aspx) –

+0

Vous pouvez raccourcir cette augmentation de l'efficacité en combinant les deux images clés dans la même animation et en définissant l'enum en ligne ' ' – Itzalive

0

Cela devrait corriger votre story-board. Cependant, n'oubliez pas qu'une fois l'animation terminée, votre contrôle est complètement opaque - invisible, mais votre propriété Visibilité est toujours définie sur Visible. Vous devez donc vous assurer que la propriété Visibility est réinitialisée ou masquée quelque part.

<Style TargetType="{x:Type FrameworkElement}" x:Key="animateFadeOut"> 
     <Style.Triggers> 
      <Trigger Property="Visibility" Value="Visible"> 
       <Trigger.EnterActions> 
        <BeginStoryboard Name="MyFadeEffect"> 
        <Storyboard> 
         <DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity" 
         From="1.0" To="0.0" Duration="0:0:0.5"/> 
        </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 
       <Trigger.ExitActions> 
        <StopStoryboard BeginStoryboardName="MyFadeEffect"/> 
       </Trigger.ExitActions> 
      </Trigger> 
     </Style.Triggers> 
     </Style> 
+0

merci pour la réponse rapide. puis-je définir la visibilité sur caché à la fin du storyboard pour corriger le problème que vous avez soulevé, "votre propriété de visibilité est toujours définie sur Visible"? – sondlerd

+0

Non, j'ai essayé, mais vous ne pouvez pas changer la valeur de la propriété qui sert de condition pour votre déclencheur. Mais maintenant vous savez comment arrêter votre animation. :) – Liz

15

Liz a raison de dire que la visibilité est toujours visible. alpha-mouse est également correct que vous devez le remettre à Caché à un moment donné. Mais cela ne fonctionnera pas si vous le réglez de nouveau avant que l'animation est terminée comme ceci:

MyControl.Visibility = System.Windows.Visibility.Visible; 
MyControl.Visibility = System.Windows.Visibility.Hidden; 

car les animations ont une priorité plus élevée (MSDN)

Vous pouvez le remettre à Cachée dans l'événement Storyboard.Completed :

private void Show() 
    { 
     MyControl.Visibility = System.Windows.Visibility.Visible; 

     var a = new DoubleAnimation 
        { 
         From = 1.0, 
         To = 0.0, 
         FillBehavior= FillBehavior.Stop, 
         BeginTime = TimeSpan.FromSeconds(2), 
         Duration = new Duration(TimeSpan.FromSeconds(0.5)) 
        }; 
     var storyboard = new Storyboard(); 

     storyboard.Children.Add(a); 
     Storyboard.SetTarget(a, MyControl); 
     Storyboard.SetTargetProperty(a, new PropertyPath(OpacityProperty)); 
     storyboard.Completed += delegate { MyControl.Visibility = System.Windows.Visibility.Hidden; }; 
     storyboard.Begin();    
    } 
+0

merci Kai, il me semble que je continue à revenir en C# pour faire avancer les choses dans WPF. Je suis relativement nouveau à WPF (j'ai travaillé dessus pendant 6 mois en 2007 puis les trois dernières semaines pour un projet). Peut-être que c'est juste la courbe d'apprentissage. Merci d'avoir signalé le storyboard. Événement terminé. – sondlerd

+0

@sondlerd: Tant que ça fonctionne, ça ne me dérange pas de le faire en code. En fait, dans ce cas je pense que faire du code est plus clair que dans xaml. –

11

Voici mon travail autour. Cela fait disparaître un contrôle avant et arrière. Au lieu de jouer avec la Visibilité, je l'ai manipulé en jouant seulement avec l'Opacité.

Merci à Kane de ce poste pour le code orginal: Fade any control using a WPF animation

Storyboard storyboard = new Storyboard(); 
TimeSpan duration = TimeSpan.FromMilliseconds(500); // 

DoubleAnimation fadeInAnimation = new DoubleAnimation() 
    { From = 0.0, To = 1.0, Duration = new Duration(duration) }; 

DoubleAnimation fadeOutAnimation = new DoubleAnimation() 
    { From = 1.0, To = 0.0, Duration = new Duration(duration) }; 
fadeOutAnimation.BeginTime = TimeSpan.FromSeconds(5); 

Storyboard.SetTargetName(fadeInAnimation, element.Name); 
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath("Opacity", 1)); 
storyboard.Children.Add(fadeInAnimation); 
storyboard.Begin(element); 

Storyboard.SetTargetName(fadeOutAnimation, element.Name); 
Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath("Opacity", 0)); 
storyboard.Children.Add(fadeOutAnimation); 
storyboard.Begin(element); 
+0

J'ai essayé cette option, et cela a fonctionné pour moi, merci! – GrayFox374

+0

Bel exemple. J'ai essayé différentes solutions pour l'animation de fondu entrant/sortant et celle-ci est très simple et claire. – Dragon

2

Mon Dieu qui a pris une éternité.Jetez un coup d'oeil à cela, cela résout le problème de l'animation lorsque la visibilité change en 'Visible' et 'Caché' en utilisant alpha et l'animation ne gèle pas.

using System.Windows; 

namespace WpfApplication4 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      button.Visibility = Visibility.Hidden; 
     } 

     private void button2_Click(object sender, RoutedEventArgs e) 
     { 
      button.Visibility = Visibility.Visible; 
     } 
    } 
} 

XAML:

<Window x:Class="WpfApplication4.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication4" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.Resources> 

      <Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}"> 
       <Style.Resources> 
        <Storyboard x:Key="FadeOut"> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" FillBehavior="Stop"> 
          <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/> 
          <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Hidden}"/> 
         </ObjectAnimationUsingKeyFrames> 
         <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" AutoReverse="False" /> 
        </Storyboard> 
        <Storyboard x:Key="FadeIn"> 
         <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" AutoReverse="False" /> 
        </Storyboard> 
       </Style.Resources> 
       <Setter Property="Width" Value="120"></Setter> 
       <Style.Triggers> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="Visibility" Value="Hidden" /> 
          <Condition Property="Opacity" Value="1" /> 
         </MultiTrigger.Conditions> 
         <MultiTrigger.EnterActions> 
          <StopStoryboard BeginStoryboardName="FadeInStoryboard" /> 
          <BeginStoryboard Name="FadeOutStoryboard" Storyboard="{StaticResource FadeOut}" /> 
         </MultiTrigger.EnterActions> 
        </MultiTrigger> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="Visibility" Value="Visible" /> 
          <Condition Property="Opacity" Value="0" /> 
         </MultiTrigger.Conditions> 
         <MultiTrigger.EnterActions> 
          <StopStoryboard BeginStoryboardName="FadeOutStoryboard" /> 
          <BeginStoryboard Name="FadeInStoryboard" Storyboard="{StaticResource FadeIn}" /> 
         </MultiTrigger.EnterActions> 
        </MultiTrigger> 
       </Style.Triggers> 
      </Style> 

     </Grid.Resources> 
     <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="200,186,0,0" VerticalAlignment="Top" Width="75" Height="38" /> 
     <Button x:Name="button1" Content="Hide it" HorizontalAlignment="Left" Margin="112,96,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/> 
     <Button x:Name="button2" Content="Show it" HorizontalAlignment="Left" Margin="200,96,0,0" VerticalAlignment="Top" Width="75" Click="button2_Click"/> 
     <Label x:Name="label" Content="{Binding ElementName=button, Path=Opacity}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/> 
     <Label x:Name="label1" Content="{Binding ElementName=button, Path=Visibility}" HorizontalAlignment="Left" Margin="10,36,0,0" VerticalAlignment="Top"/> 

    </Grid> 
</Window>