WPF storyboard animation repeats - wpf

I have a trigger that fires off an OptionsShow storyboard animation when a button is clicked. This works with no problem. When I click an options button that I created, I made a grid fade in over it, similar to a custom tooltip. When the user leaves that grid, I make it fade out with the OptionsHide storyboard animation. If I leave the grid and quickly hover over the grid before it completely goes away, the grid constantly flashes.
It seems that the constant flashing occurs because the initial hide animation cannot complete, but I can't seem to figure out how to debug this. I don't have an "OnEnter" grid trigger to reshow the grid, so I'm not really sure when it shows the grid with opacity 100%, begins to fade and the constantly repeats this process.
If anyone has any experience with this, any help or info would be great.
<Window.Resources>
<Storyboard x:Key="OptionsShow">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Border">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OptionsHide">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Border">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<!--This is my button in my menu bar. On click I show my tooltip grid.-->
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource OptionsShow}"/>
</EventTrigger>
<!--When I leave the tooltip grid, make the tooltip grid fade out.-->
<EventTrigger RoutedEvent="UIElement.MouseLeave" SourceName="Border">
<BeginStoryboard x:Name="OptionsHide_BeginStoryboard" Storyboard="{StaticResource OptionsHide}"/>
</EventTrigger>
</Window.Triggers>

Related

How to start animation, wait for 'X' seconds and then undo animation?

I have an animation that brings a text block down when I have an error that I want to display to the user. Currently, it comes down in .5 seconds. Is there a way to bring it down in .5 seconds, keep it there for 10 seconds, and then hide it in .5 seconds? I found the auto reverse property, which takes care of the beginning and ending, but I have not found a way to keep the text block displayed for a specified period of time. Any help would be appreciated!
<Window.Resources>
<Storyboard x:Key="MessageSlide" AutoReverse="True">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="textBlock">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="50"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource MessageSlide}"/>
</EventTrigger>
</Window.Triggers>
Add another KeyFrame that just holds the value:
<DoubleAnimationUsingKeyFrames ... AutoReverse="True">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="50"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:5.5" Value="50"/>
</DoubleAnimationUsingKeyFrames>
You may as well just set the animation's Duration:
<DoubleAnimationUsingKeyFrames ... Duration="0:0:5.5" AutoReverse="True">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="50"/>
</DoubleAnimationUsingKeyFrames>

WPF Storyboard animation isn't fluid

Here's what I'm trying to do:
Make control1 Visible, make control2 Collapsed, animate opacity from 1 to 0 on control 1 over .8 seconds.
immediately after that is done, do this:
Make control1 Collapsed, make control2 Visible, animate opacity from 0 to 1 on control2 over .8 seconds.
I just can't get it to be fluid and I'm out ideas. here's what I have:
<Storyboard x:Key="sb">
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.8000000" Storyboard.TargetName="MainTabControl" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8000000" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.8000000" Storyboard.TargetName="MainTabControl" Storyboard.TargetProperty="(UIElement.Opacity)">
<LinearDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<LinearDoubleKeyFrame KeyTime="00:00:00.8000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00.8000000" Duration="00:00:00.8000000" Storyboard.TargetName="SearchProjectsView" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8000000" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8000000" Duration="00:00:00.8000000" Storyboard.TargetName="SearchProjectsView" Storyboard.TargetProperty="(UIElement.Opacity)">
<LinearDoubleKeyFrame KeyTime="00:00:00.0000000" Value="0"/>
<LinearDoubleKeyFrame KeyTime="00:00:00.8000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
It isn't clear from your question why you would animate the Opacity and Visbility at the same time, but your problem is that the animation of the Visibility of the second control should start immediately, not after 0.8 seconds.
This should work:
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="MainTabControl" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="SearchProjectsView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="MainTabControl" Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:0.8"/>
<DoubleAnimation
Storyboard.TargetName="SearchProjectsView" Storyboard.TargetProperty="Opacity"
From="0" To="1" BeginTime="0:0:0.8" Duration="0:0:0.8"/>
</Storyboard>

WPF Animated UserControl - Canvas

In developing for my project I am trying to create a usercontrol element containing many canvas layers. It's a vector image imported with Blend. I created a .GIF model for the initial frame, and set a frame rate for each layer (40ms). In creating a .gif its to easy to control a frame speed for each layer. I'm now trying to make that motion in WPF using Storyboard, and to control appearance for each layer I'm using Visibility state like in my source code :
<UserControl.Resources>
<Storyboard x:Key="ProgressAnimation" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00.0000000" Storyboard.TargetName="Layer1" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00.2000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4500000" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00.1000000" Storyboard.TargetName="Layer2" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00.2000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4500000" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00.2290000" Storyboard.TargetName="Layer3" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="00:00:00.2000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.4500000" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
And of course I set a trigger :
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="ProgressAnimationBeginStoryboard" Storyboard="{StaticResource ProgressAnimation}"/>
</EventTrigger>
</UserControl.Triggers>
Now the code works perfectly, but I truing do increase speed of the element, and got in trouble with that. Wen I set SpeedRation for my StoryBoard the element flashing/blinking and works very unstable.
Please help me to understand and learn a better method to do it right.

WPF blink an ellipse fill animation

I was looking at this excellent post:
How do I make an ellipse blink?
Is there a way to not have the blink fade and instead just change the color immediately with no fade?
Use DiscreteColorKeyFrame. Set the KeyTime to specify when you want it to trigger.
Here is an example of a blinking Ellipse. Fill alternates between Red and Blue every second
<Ellipse Fill="Red">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
Duration="0:0:2"
FillBehavior="HoldEnd"
RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Red"/>
<DiscreteColorKeyFrame KeyTime="0:0:1" Value="Blue"/>
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>

Setting the Visibility of an Element to Collapsed when Storyboard completes using XAML

I have a storyboard animation that fades a control out of view using the Opacity property. When it completes, I want to set the Visibility of the control to Collapsed.
I'd like to be able to do the reverse as well... Set the Visibility to Visible and then use a storyboard to fade the control into view.
I know I can hook up events, but I would like to do this all in XAML. Is it possible?
you can do this in the animation as well
<Window.Resources>
<Storyboard x:Key="OnLoaded1">
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="button" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.8000000" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01.4000000" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
</EventTrigger>
</Window.Triggers>

Resources