WPF animation won't repeat - c#

There is an MSDN article that specifically addresses my question but it does not provide a solution in my case:
http://msdn.microsoft.com/en-us/library/aa970493(v=vs.110).aspx
I want to trigger an animation from my view model where I fade out one textblock and subsequently fade in another textblock to appear like the text is updating. I need to run this animation 3 times in a row. It would be nice if I could just set the Animate property to "On" 3 times in a row and it would start the animation repeatedly but this does not seem to work.
The next best option would be to notify my ViewModel when the animation is complete allowing me to set the Animate property to "Off" and then change it back to "On". This doesnt seem to work for 2 reasons. If "Off" and "On" are set in the same method call the View doesnt seem to update the property until after that threads method execution is complete. And the second problem is that the Completed event of the animation is NEVER CALLED...this is something that is a constant issue for me.
Any other suggestions?
Here is a sample of the code:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Animate}" Value="On">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- Show one textblock and hide the other -->
<DoubleAnimation
Storyboard.TargetName="txtMessage"
Storyboard.TargetProperty="Opacity"
To="1.0" Duration="0:0:0" />
<DoubleAnimation
Storyboard.TargetName="txtMessage2"
Storyboard.TargetProperty="Opacity"
To="0.0" Duration="0:0:0" />
<!-- Now animate the text blocks back to their original setting -->
<DoubleAnimation
Storyboard.TargetName="txtMessage"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:1"
Completed="Animation_Completed" />
<DoubleAnimation
Storyboard.TargetName="txtMessage2"
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:1"
BeginTime="0:0:1"
Completed="Animation_Completed" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
Again, for some reason the Animation_Completed handler is never hit...
Updated 5/8 to spell out more specifically what I need this animation to do.

Related

WPF EventTriggers.EnterActions not working

WPF EventTriggers.EnterActions not working.
Ust two similar Storyboard in Trigger.Actions - work, but in Trigger.EnterActions - no.
Trigger on checkbox 2 works, but trigger on checkbox 1 not firing.
WPF EventTriggers.EnterActions not working.
Ust two similar Storyboard in Trigger.Actions - work, but in Trigger.EnterActions - no.
<StackPanel>
<CheckBox Content="checkbox 1">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<EventTrigger.EnterActions>
<BeginStoryboard Name="enter">
<Storyboard>
<DoubleAnimation From="1"
To="0.5"
Duration="0:0:1"
Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.EnterActions>
<EventTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="enter"/>
</EventTrigger.ExitActions>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
<CheckBox Content="checkbox 2">
<CheckBox.Triggers>
<EventTrigger RoutedEvent="CheckBox.Checked">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard >
<DoubleAnimation From="1"
To="0.5"
Duration="0:0:1"
Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</CheckBox.Triggers>
</CheckBox>
</StackPanel>
WPF EventTriggers.EnterActions not working. Ust two similar Storyboard in Trigger.Actions - work, but in Trigger.EnterActions - no.
See documentation TriggerBase.EnterActions:
Gets a collection of TriggerAction objects to apply when the trigger object becomes active. This property does not apply to the EventTrigger class.

Skip storyboard cleanly in ControlTemplate

I have a Style for a ToggleButton which defines a ControlTemplate. My ToggleButton is animated when it changes states, but i don't want it to animate when i navigate to a new page. So, i added an EventTrigger on the Loaded event with SkipStoryboardToFill to avoid this behavior, and it does what i want.
My only issue now, is that when i add a new ToggleButton, it tries to skip storyboards which haven't been started, generating an Animation Warning ("Unable to perform action because the specified Storyboard was never applied to this object for interactive control.") which seems to impact my application's performance.
I could probably work around that but i'd rather solve the actual problem. Is there a way i could add a condition in my EventTrigger ?
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="ToggleButton.Loaded">
<SkipStoryboardToFill BeginStoryboardName="checkedSB" />
<SkipStoryboardToFill BeginStoryboardName="uncheckedSB" />
</EventTrigger>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}"
Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Name="checkedSB">
<Storyboard Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="Margin">
<ThicknessAnimation To="20 1 2 1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Name="uncheckedSB">
<Storyboard Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="Margin">
<ThicknessAnimation To="2 1 2 1" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
Is there a way i could add a condition in my EventTrigger ?
Short answer: No.
An EventTrigger always applies when the corresponding event is being raised.
If you want to trigger the animations conditionally, you should either switch to using a MultiDataTrigger or implement the animations programmatically.

Is it possible to animate the transition when a controls' data binding changes?

We have a UserControl that mainly includes a XamTileManager (the actual control shouldn't matter) which is bound to a list of items. When the binding changes, we want to animate the transition between the old and new data with an arbitrary animation. Is that generally possible in WPF?
The alternative would of course be to have two UserControls and animate the change between them, but we want to avoid that if possible.
You can put a trigger inside the item with a storyboard. When the data changes the trigger will fire and launch the storyboard animation. I found this example which does it for a data binded textblock:
<TextBlock x:Name="tbMessage" Text="{Binding Path=StatusBarText, NotifyOnTargetUpdated=True}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:0" To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1.0" To="0.0" BeginTime="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
(source)
If that isnt quite what you want you can write your own animation by using the Binding.TargetUpdated event.

Animating WPF buttons from inside a style

I'm currently trying to make buttons on my forms animate using WPF - this is part of a University course, so it's all about demonstrating knowledge rather than looking good.
We've been shown how to animate per-button, but since I want the animation to be the same on every button I'm using a style - something we've not been taught and which finding documentation for is like finding evidence of Big Foot, IMO.
My code so far is this:
<Style TargetType="{x:Type Button}" x:Key="ButtonAnimation">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Angle"
To="360" Duration="0:0:1"
FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="ScaleY"
To="0.1" Duration="0:0:0.5"
FillBehavior="Stop" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="ScaleX"
To="0.1" Duration="0:0:0.5"
FillBehavior="Stop" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
The TargetProperty="" values are incorrect, and for the life of me I cannot find anywhere online that demonstrates what should be there. The values currently there are what you would have if the animation was applied to each button rather than in a style.
How do I get this to work? What is the correct TargetProperty?
I think this...
Storyboard.TargetProperty="Angle"
...should be...
Storyboard.TargetProperty="(Button.RenderTransform).(RotateTransform.Angle)"
And the other ones:
Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleY)"
Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleX)"
You might have to replace RenderTransform with LayoutTransform, depending on what you are using in your markup.
However, this will only work if you only have one of the two Transforms, i.e. RotateTransform or ScaleTransform. If you have them in a TransformGroup, things get even more complicated. If you have defined the RotateTransform as the first child and the ScaleTransform as the second child of the TransformGroup, then this should work (not tested):
(Button.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)
(Button.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.X)
(Button.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.Y)
However, you have to be careful when changing the order of the Transforms or remove one of them because this will break your animations...
Good luck!

How to animate ListBox Items on MouseEnter and MouseLeave events using C#/WPF?

I can't capture/trigger OnMouseEnter or OnMouseLeave events through C# code for list items. To be clear, I don't need an OnSelectedItem event.
What I want to do is to be able to handle the OnMouseEnter and OnMouseLeave events for ListBoxItem which will start the DoubleAnimation for that ListBoxItem - I want to enlarge its font on MouseEnter and restore to original size on MouseLeave.
Any ideas? Thanks.
Something like this (as part of the ListBox's DataTemplate):
<DataTemplate.Triggers>
<EventTrigger
SourceName="BorderControl"
RoutedEvent="TextBlock.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderControl"
Storyboard.TargetProperty="Background.Color"
To="DarkRed" Duration="00:00:00.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger
SourceName="BorderControl"
RoutedEvent="TextBlock.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderControl"
Storyboard.TargetProperty="Background.Color"
To="WhiteSmoke" Duration="00:00:00.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</DataTemplate.Triggers>
via http://www.dotnet-blog.com/index.php/2009/01/29/how-to-style-and-animate-a-wpf-listbox/

Categories