I have a WPF Datatemplate that contains a some DataTriggers that start animating the color of a visual. How can I start the animation beginning with the actual value the color property currently has?
Since there might be another animation currently active I can not start a new one but when I remove the animation using DataTriggers ExitAction and RemoveStoryboard the position property is set back to its default value.
Instead I would like handoff one to the other.
Is this a limitation of WPF that simply can not be done?
<DataTrigger Binding="{Binding Path=State}" Value="Active">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="activeStoryboard" HandoffBehavior="SnapshotAndReplace">
<Storyboard>
<ColorAnimation To="Green" FillBehavior="HoldEnd" Duration="00:00:0.25"
Storyboard.TargetName="stateBrush"
Storyboard.TargetProperty="Color" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="activeStoryboard" />
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=State}" Value="Error">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="errorStoryboard" HandoffBehavior="SnapshotAndReplace">
<Storyboard>
<ColorAnimation To="Red" FillBehavior="HoldEnd" Duration="00:00:0.25"
Storyboard.TargetName="stateBrush"
Storyboard.TargetProperty="Color" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="errorStoryboard" />
</DataTrigger.ExitActions>
</DataTrigger>
It should just work if you start the second animation, even if FillBehavior is set to Stop!
Check the following section on msdn: FillBehavior="Stop" and HandoffBehavior with Multiple Animations
Related
I want to stop WPF StoryBoard after property of control IsAnimating is changed to false, but I need to stop animation not instantly, but first complete currently running animation cycle and then stop it (I'm using this XAML now, but it stops my animation instantly):
<UserControl x:Class="App.Controls.ProgressCircle"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" >
<Ellipse Name="Circle" Width="30" Height="30" Fill="Green" >
<Ellipse.Style>
<Style>
<Style.Resources>
<Storyboard x:Key="Pulsing">
<DoubleAnimation From="30.0" To="0.0" Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever"
Storyboard.TargetProperty="Width" />
<DoubleAnimation From="30.0" To="0.0" Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever"
Storyboard.TargetProperty="Height" />
</Storyboard>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding IsAnimating, ElementName=me}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Pulsing" Storyboard="{StaticResource Pulsing}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Pulsing" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</UserControl>
A "quick and dirty" solution would be to start a new animation in the DataTrigger.ExitActions that animates the height and width properties to the values they had before the whole animation was started. This could look like this:
<Style.Triggers>
<DataTrigger Binding="{Binding IsAnimating, ElementName=me}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Pulsing" Storyboard="{StaticResource Pulsing}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1"
Storyboard.TargetProperty="Height" />
<DoubleAnimation Duration="0:0:1"
Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
The important thing is that if you do not set the the To value on an animation, then the target value will be the one that the dependency property previously had (the local value of 30.0 in this case). You do not have to stop the 'Pulsing' storyboard in this case because this is automatically done when you start a new storyboard that animates the same dependency properties.
Obviously, this is not the optimal solution as you do not integrate the current status of the Pulsing animation (i.e. at which point in time it was when IsAnimating is set to false). As far as I know, there is no built-in functionality in WPF to achieve this kind of functionality, but it might be possible to implement a custom ConstrallableStoryboardAction that respects all these information and that can be set in the DataTrigger.ExitActions instead. It might also be worth your while to check some of Animation How-To topics in the MSDN library.
How do I set the Background after a Storyboard ColorAnimation completes in XAML?
My ColorAnimation runs which makes Background flash red but after it returns to the original background colour (white) I would like it to remind red but i can't see how to do this.
My xaml is below - thanks
<Grid Name="cell" Background="White">
<Grid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding DataItem.ControlValue, Converter={StaticResource IsNotNullOrEmptyConverter}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard x:Name="Blink" >
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Blink" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
Set AutoReverse to False on your ColorAnimation if you don't want it to revert back to original value i.e White.
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="False"/>
UPDATE
Add another ColorAnimation in your Storyboard which will begin after your first ColorAnimation completes may be after 4 sec interval.
<BeginStoryboard>
<Storyboard x:Name="Blink">
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
RepeatBehavior="3x" Duration="0:0:1" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red"
Duration="0:0:1" BeginTime="0:0:4"/>
</Storyboard>
</BeginStoryboard>
I want the animation to stop when the boolean CanAnimate becomes false. It starts on true, so how do i tell it to stop when CanAnimate is false? (The CanAnimate bool is set inside a SelectedItem setter)
<Border BorderBrush="Black" BorderThickness="2" Margin="1" Name="ReviewNote">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding CanAnimate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Border.Opacity)"
From="1.0" To="0.0" AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock/>
</Border>
You can try using the ExitActions on the DataTrigger to stop the animation, by overriding with another animation. For instance:
<DataTrigger Binding="{Binding CanAnimate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Border.Opacity)"
From="1.0" To="0.0" AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="(Border.Opacity)"
From="0.0" To="0.0" Duration="0:0:0.0" FillBehavior="HoldEnd" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
Alternatively, there is a way to stop storyboards in XAML by name, again you could use ExitActions for this. This previous question shows the way.
Hope this helps!
I am trying to translate a rectangle on the Y access using a DataTrigger.
It works great except I want the rectangle to move from its current transformed state instead of restarting from the initialstate.
I would like an all XAML solution.
I have tried setting the Completed property but WPF won't allow that.
Thanks in advance.
<DataTrigger Binding="{Binding CurrentFloor}" Value="5">
<DataTrigger.EnterActions>
<BeginStoryboard Name="sb5">
<Storyboard>
<DoubleAnimation
To="5"
Storyboard.TargetProperty="RenderTransform.Y"
Duration="0:0:2"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="sb5" />
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentFloor}" Value="4">
<DataTrigger.EnterActions>
<BeginStoryboard Name="sb4">
<Storyboard>
<DoubleAnimation
To="75"
Storyboard.TargetProperty="RenderTransform.Y"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="sb4" />
</DataTrigger.ExitActions>
</DataTrigger>
Use <DoubleAnimation By="5" .../> not <DoubleAnimation To="5" .../>
I want to change the background of a framework element when the DragEnter event is fired and revert its background when the DragLeave event is fired. Additionally, I want this applied in a style.
Heres what I have currently:
<EventTrigger RoutedEvent="Button.DragEnter">
<BeginStoryboard x:Name="DragHoverStoryboard">
<Storyboard>
<DoubleAnimation Storyboard.Target="??????????"
Storyboard.TargetProperty="Background"
Duration="0:0:0"
To="{DynamicResource HoverBrush}" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.DragLeave">
<StopStoryboard BeginStoryboardName="DragHoverStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Drop">
<StopStoryboard BeginStoryboardName="DragHoverStoryboard" />
</EventTrigger>
The problem here is that I can't apply target by a name because this style can be applied to any FrameworkElement. How do I apply the target to the element that the Style is attached to?
Storyboard.Target is not the problem, just leave it out. However, you need to change the rest of the animation. To animate a color, use a ColorAnimation instead of a DoubleAnimation. Also, the property "Background" does not contain a color but a brush, so animate the property "Background.Color" instead. Here is a working example:
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.DragEnter">
<BeginStoryboard x:Name="DragHoverStoryboard">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color"
Duration="0:0:0" To="Green" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.DragLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color"
Duration="0:0:0" To="Red" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>