2010-11-30 28 views
15

En mi aplicación WPF, tengo un control de retroalimentación que quiero que aparezca después de que una acción del usuario finalice (guardar datos, eliminar ...). La visibilidad se establece en Oculto para comenzar y el estilo se establece en el estilo animadoFadeOut definido como un recurso (consulte a continuación). Luego quiero configurar el texto y controlar la Visibilidad para que sea visible en mi código C# y hacer que el control de retroalimentación muestre el mensaje y desaparezca después de 5 segundos y permanezca oculto (Visibility.Hidden).Desvanecimiento WPF en un control

El siguiente XAML funciona la primera vez que llamo control.Visiblity = Visibility.Visible pero el control no vuelve a aparecer la segunda vez. Me imagino que eso se debe a que la animación todavía se está ejecutando, lo que tiene control sobre el control de retroalimentación. Luego intenté establecer FillBehavior en "Stop", pero eso solo hizo que el control se volviera visible y lo quiero ocultar. Luego, con FillBehavior = "Stop", traté de establecer un disparador "cuando Opacidad = 0, establezca la Visibilidad en Oculto". El gatillo no pareció dispararse y me quedé con el control visible una vez más después de que la animación se completó.

Por favor, ayúdenme a señalar lo que estoy haciendo mal aquí.

Alternativamente, si puede sugerir una manera mejor de mostrar un control que se desvanece después de 5 segundos y se puede invocar una y otra vez, se lo agradecería.

Gracias!

<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

Me tomó un enfoque ligeramente diferente para solucionar el problema ... Lo escribí en C#. (Consulte la publicación a continuación: la sección de comentarios es demasiado pequeña para las publicaciones de códigos) – sondlerd

Respuesta

28

El problema es que después de la animación completa de su control todavía tiene Visibilidad = visible, por lo que no puede ser introducida de nuevo.
Prefiero usar la animación que hace todo, primero muestra el control y luego lo oculta.

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

y utilizarlo como sigue:

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

gracias, Alpha-Mouse. Respondió la pregunta que publiqué a continuación a Liz. Otra pregunta, una vez que termina la animación, ¿la opacidad = 0.0 o es solo eso en la animación? Lo pregunto porque cuando configuré FillBehavior en Stop, la opacidad volvió a 1.0. – sondlerd

+0

@sondlerd: cuando FillBehaviour es Stop, entonces sí, [el valor de la propiedad vuelve a su valor original] (http://msdn.microsoft.com/en-us/library/system.windows.media.animation.fillbehavior. aspx) –

+0

Puede acortar este aumento de la eficiencia combinando los dos fotogramas clave en la misma animación y definiendo enum inline ' ' – Itzalive

0

Esto debería solucionar el guión gráfico.

Sin embargo, recuerde que una vez que se completa la animación, su control es completamente opaco, invisible, pero su propiedad Visibilidad aún está configurada en Visible. Por lo tanto, deberá asegurarse de que la propiedad de visibilidad se restablezca a oculta o colapsada en algún lugar.

<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

gracias por la respuesta rápida. ¿Puedo establecer la visibilidad en Oculto al final del guión gráfico para solucionar el problema que planteaste, "tu propiedad Visibilidad aún está configurada en Visible"? – sondlerd

+0

No, lo intenté, pero no puede cambiar el valor de la propiedad que sirve como condición para su desencadenante. Pero ahora sabes cómo detener tu animación. :) – Liz

15

Liz es correcta acerca de Visibility still being Visible. alpha-mouse también es correcto que necesita volver a establecerlo en Hidden en algún punto. Pero no va a funcionar si cambia de nuevo antes de que la animación se completa de esta manera:

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

porque animaciones tienen mayor precedencia (MSDN)

Se puede ajustar de nuevo en Oculto en caso 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

gracias Kai, parece que sigo volviendo a C# para hacer las cosas en WPF. Soy relativamente nuevo en WPF (trabajé en él durante 6 meses en 2007 y luego en las últimas tres semanas para un proyecto). Tal vez es solo la curva de aprendizaje. Gracias por señalar el guión gráfico. Evento completo. – sondlerd

+0

@sondlerd: Mientras haga las cosas, no me importa hacerlo en código. De hecho, en este caso creo que hacerlo en código es más claro que en xaml. –

11

Aquí está mi trabajo. Esto desvanece un control hacia dentro y hacia atrás nuevamente. En lugar de jugar con Visibility, lo manejé jugando solo con Opacity.

Gracias a Kane de este post para el código original: 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

Intenté esta opción, y funcionó para mí, ¡gracias! – GrayFox374

+0

Buen ejemplo. Probé diferentes soluciones para la animación de fundido de entrada/salida y esta es muy simple y clara. – Dragon

2

Dios mío que tuvo siempre.Eche un vistazo a esto, resuelve el problema de animar a los cambios de Visibilidad a 'Visible' y 'Oculto' usando alfa y la animación no se congelará.

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>