I'm trying to create a marching dot animation where there's a series of small circles and one will grow a bit and change color, then the next will, and so on, and this will bounce back and forth. The animation will be triggered by a bool value in the ViewModel.
I actually had this working before deciding to use the MVVM pattern, it was easy: I had the storyboard in the Page.Resources tags and called the animation from code behind on button click. Now I'm stuck with this decoupled, it seems no matter what I try there's always an error of some kind.
Here's the dots in xaml:
<Grid Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Ellipse Name="Dot5" Grid.Row="1" Grid.Column="0" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot4" Grid.Row="1" Grid.Column="1" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot3" Grid.Row="1" Grid.Column="2" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot2" Grid.Row="1" Grid.Column="3" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot1" Grid.Row="1" Grid.Column="4" Style="{StaticResource ConnectionMeterOff}"/>
</Grid>
And my current animation:
<DataTemplate x:Key="MarchingDots">
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsConnecting}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Name="MarchingDotsAnimation">
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimation Storyboard.TargetName="Dot1" BeginTime="0:0:0.1"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot1" BeginTime="0:0:0.1"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot2" BeginTime="0:0:0.2"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot2" BeginTime="0:0:0.2"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot3" BeginTime="0:0:0.3"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot3" BeginTime="0:0:0.3"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot4" BeginTime="0:0:0.4"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot4" BeginTime="0:0:0.4"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot5" BeginTime="0:0:0.5"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot5" BeginTime="0:0:0.5"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
I'm pretty sure my issue isn't the binding, but either that the animation isn't attached to the dots, or how I'm trying to wrap it to get access to the triggers. If I keep it just a Storyboard like before, I don't have anything to trigger it. If I try a style, it complains that I can use "Storyboard.TargetName". I've also tried EventTriggers. And copious amounts of Googling...all the examples seem to be single elements (like a rectangle) where the storyboard can be attached to the element's style.
I'm sure this is simple, but what am I doing wrong?
This needs a bit of cleanup, but it will get you started. First declare your animations:
<Storyboard x:Key="Storyboard1" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard3" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard4" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard5" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
I'm going to build it out of ellipses, so create a base style for them:
<Style x:Key="EllipseStyle" TargetType="Ellipse">
<Setter Property="Fill" Value="Black" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
<Setter Property="Margin" Value="10" />
<Setter Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Setter.Value>
</Setter>
</Style>
Then create five ellipses, assign each one it's corresponding storyboard and use a DataTrigger to turn the animation on and off:
<UniformGrid Columns="5">
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard1" Storyboard="{StaticResource Storyboard1}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard1" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard2" Storyboard="{StaticResource Storyboard2}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard2" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard3" Storyboard="{StaticResource Storyboard3}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard3" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard4" Storyboard="{StaticResource Storyboard4}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard4" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard5" Storyboard="{StaticResource Storyboard5}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard5" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</UniformGrid>
<CheckBox Content="Animate" IsChecked="{Binding Animating}" HorizontalAlignment="Center"/>
</StackPanel>
I'm assuming there's a property in your view model called Animating that you're using to control this, I've added a checkbox to this code as well for testing:
EDIT: just updated the animations to get rid of that flicker on the right.
Related
I have a TextBlock which displays an image from a font.
I want the TextBlock to pulsate when a boolean flag is set in the ViewModel.
I found the Answer given by Chris W in this similar Stackoverflow question. The second box in his example is just what I want. The pulsating example is basically:
<Storyboard x:Key="Pulse">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Storyboard.TargetName="PulseBox"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
Storyboard.TargetName="PulseBox"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
As I knowing nothing about triggers and Storyboards in WPF, I gave it a try to put this in a DataTrigger but failed big time.
I came up with this:
<TextBlock Text="SomeCodeToAImageInAFont" Background="CornflowerBlue">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Activate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Activate is a boolean property in the ViewModel.
When I set the Activate bool to True I get this exception:
System.InvalidOperationException
The property [Unknown] does not point to a DependencyObject in the path (0).(1)[0].(2).
It's quite clear that these lines are incorrect:
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
Unfortunately I don't understand the exception and how to fix it.
Any suggestions?
Since you access a transformation RenderTransform in your animation, you have to add it to the element. I also changed RepeatBehavior to do execution 10 times, or you can set it to RepeatBehavior="Forever".
<TextBlock Text="SomeCodeToAImageInAFont" Background="CornflowerBlue">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Activate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames RepeatBehavior="10x"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames RepeatBehavior="10x"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
I have ran into an issue when more than one DataTriggers are bound to the same ViewModel property. After investigation, I have noticed that always the last one wins. How can I overcome the problem? Thanks
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowGrid}" Value="false">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="0" Value="50"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=ShowGrid}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="50"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
BTW, this works fine:
<DataTrigger Binding="{Binding Path=ShowGrid}" Value="false">
<Setter Property="Height" Value="0"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=ShowGrid}" Value="true">
<Setter Property="Height" Value="100"></Setter>
</DataTrigger>
So, it is got to be storyboard related, any clues?
Storyboard's FillBehavior defaults to HoldEnd, change it to FillBehavior=Stop
The default behavior is to keep the last values of a Storyboard set, tell it to reset them after it completed.
Edit
Ok now I understand what you want. You've to use DataTrigger.ExitActions:
<DataTrigger Binding="{Binding Path=ShowGrid}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="50"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="0" Value="50"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
Just tried it and it seems to do what you want. Don't forget to remove the other DataTrigger.
I want to make an image flash a set number of times, when I set its Visibility to Visible. And when it's finished flashing, I want it to make itself Collapsed again.
Here's a simple version of what I'm trying to do:
<Image Visibility="Collapsed"
Margin="0,0,3,0"
Width="24"
Source="blah"
Height="24">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="Visibility"
Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard RepeatBehavior="5x"
x:Name="flashingStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
Duration="0:0:1"
FillBehavior="Stop">
<DiscreteDoubleKeyFrame Value="0"
KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="1"
KeyTime="0:0:0.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Can I do this in XAML?
If you know how many times it will be flashed then you can set BeginTime correspondingly the number of times your flashing comes along.
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames RepeatBehavior="5x" Storyboard.TargetProperty="Opacity" Duration="0:0:1">
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="1" KeyTime="0:0:0.5" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:5" Duration="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
I asked a previous question about adding a TabItem and I was told that using Buttons would be better and just animation to them. So I went ahead today and researched about this but I have come to an issue.
This is the XAML I have:
<Button Height="43" HorizontalAlignment="Left" IsEnabled="True" IsHitTestVisible="True" Margin="363,309,0,519" Name="home_btn" VerticalAlignment="Stretch" Width="346" >
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="Normal" Source="Images/Normal1.png" />
<Image Name="Hover" Source="Images/Hover1.png" Opacity="0"/>
<Image Name="Pressed" Source="Images/view3.png" Opacity="0" Width="346" />
</Grid>
<ControlTemplate.Resources>
<Storyboard x:Key="MouseDownTimeLine">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Pressed" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="Pressed" Storyboard.TargetProperty="Width" From="274" To="300" Duration="00:00:00">
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="MouseUpTimeLine">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Pressed" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="MouseEnterTimeLine">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Hover" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="MouseExitTimeLine">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Normal" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="00:00:00.00" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource MouseDownTimeLine}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource MouseUpTimeLine}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource MouseEnterTimeLine}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource MouseExitTimeLine}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
From this when I hover over my First image it will trigger the second image. The difference between these two is just the color, so it's not the problem.
When I click the button I want an arrow to appear next to the box (so i need the canvas to grow bigger) I created my Images in Photoshop and the third image I made bigger but it doesn't work, this is what happens.
As you can see from the second picture I want to aligned from the left and come out at the right. I have tried HorizontalAlignment="Left" and this doesn't work.
I have a combobox, which is bound to an enumeration of animations. We have the requirement such that if an animation style is selected in the combo box, the corresponding animation should be triggered on a textblock. i have 3 animations, namely fade, scale and blink. While blink is working fine, fade and scale doesnt work. it works only for the first time when the screen loads and then thereafter, even if the selection is changed to fade/scale, teh animation is not triggered. As if now, i have triggered the animation using a data trigger, and that is when this issue started coming, but the animation was triggered perfectly when we tried to use an event trigger. My code is as below. Could someone help me as to what is it that I am doing wrong and how it can be rectified.
Animations:
<Storyboard x:Key="Fade">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Scale">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Blink">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames RepeatBehavior="3x" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
The combobox, textblock and data triggers used to trigger the animation:
<telerik:RadComboBox x:Name="animationTypeComboBox"
Foreground="White"
Width="180"
ItemsSource="{Binding Source={StaticResource AnimationTypeEnumValues}}"
SelectedItem="{Binding SelectedAnimationType, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" >
</telerik:RadComboBox>
<TextBlock x:Name="testMsg" Text="Test message" VerticalAlignment="Center" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource Subheading}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedAnimationType}" Value="{x:Static ent:AnimationType.Fade}">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Fade}"/>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedAnimationType}" Value="{x:Static ent:AnimationType.Scale}">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Scale}"/>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedAnimationType}" Value="{x:Static ent:AnimationType.Blink}">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink}"/>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
I made few changes in your code to make it work in my local system.... here is a solution to your problem..
<TextBlock x:Name="testMsg" Text="Test message" VerticalAlignment="Center" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem,ElementName=AnimStyles}" Value="Fade">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="Scale"/>
<RemoveStoryboard BeginStoryboardName="Blink"/>
<BeginStoryboard Name="Fade">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem,ElementName=AnimStyles}" Value="Scale">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="Fade"/>
<RemoveStoryboard BeginStoryboardName="Blink"/>
<BeginStoryboard Name="Scale">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem,ElementName=AnimStyles}" Value="Blink">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="Fade"/>
<RemoveStoryboard BeginStoryboardName="Scale"/>
<BeginStoryboard Name="Blink">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames RepeatBehavior="3x" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
In the above code instead of taking story boards in resources i am taking then in line... and removing the other storyboards before starting the actual storyboard...
This means what ever be the behavior effected by the previous Storyboards will be removed and every time animation works as like a new one..