In my WPF app, I have a feedback control that I want to appear after a user action completes (save data, delete...). The visibility is set to Hidden to begin and style set to the animateFadeOut style defined as a resource (see below). Then I want to set the text and control Visibility to visible in my C# code and have the feedback control display the message and fade out after 5 seconds and remain hidden (Visibility.Hidden).
The following XAML works the first time I call control.Visiblity= Visibility.Visible but the control doesn't reappear the second time. I figure that is because the animation is still running, which has control over the feedback control. I then tried to set FillBehavior to "Stop" but that just made the control visible again and I want it hidden. Then, with FillBehavior="Stop", I tried to set a trigger "when Opacity = 0, set the Visibility to Hidden". The trigger didn't seem to fire and I was left with the visible control once more after the animation completed.
Please help point out what I am doing wrong here.
Alternatively, if you can suggest a better way to display a control that fades after 5 seconds and can be called over and over, I would appreciate it.
Thanks!
<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>
The problem is that after your animation completes your control still has Visibility=Visible, so it cannot be entered again.
I would rather use animation that does the whole thing, first shows the control, then hides it.
<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>
And use it as follows:
((Storyboard)FindResource("animate")).Begin(someControl);
Liz is correct about Visibility still being Visible. alpha-mouse is also correct that you need to set it back to Hidden at some point. But it won't work if you set it back before the animation is completed like this:
MyControl.Visibility = System.Windows.Visibility.Visible; MyControl.Visibility = System.Windows.Visibility.Hidden;
because animations take higher precedence (MSDN)
You can set it back to Hidden in Storyboard.Completed event:
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(); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With