How to prevent a storyboard from playing automatically when page loads? - c#

This issue doesn't seem to have any cause. There is no Storyboard.Begin() called anywhere in code (searched with a 'Find all' in current project) and no triggers as far as can be seen.
Using Storyboard.Stop() in Page_Loaded event for every single Storyboard present fixes this issue but it seems more like a hack than a solution.
What causes this behaviour and how can it be fixed?
The similar issue from here has a solution but it does not apply in this case: not using Blend
My code is as follows:
<Page.Resources>
[...]
<BeginStoryboard x:Name="StartButtonTranslateAndShrinkStoryboard">
<Storyboard RepeatBehavior="0x">
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.TranslateX)"
From="0" To="140" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.TranslateY)"
From="0" To="300" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.ScaleX)"
From="3" To="1" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.ScaleY)"
From="3" To="1" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
[...]
</Page.Resources>

Don't put it in the <BeginStoryboard> tags, that is a trigger that starts the storyboard. You can assign the name of the storyboard (in your case StartButtonTranslateAndShrinkStoryboard) to the storyboard itself instead of the trigger and it should work.
<Page.Resources>
[...]
<Storyboard RepeatBehavior="0x" x:Name="StartButtonTranslateAndShrinkStoryboard">
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.TranslateX)"
From="0" To="140" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.TranslateY)"
From="0" To="300" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.ScaleX)"
From="3" To="1" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="StartButtonTransform"
Storyboard.TargetProperty="(CompositeTransform.ScaleY)"
From="3" To="1" Duration="0:0:1"/>
</Storyboard>
[...]
</Page.Resources>
From MSDN:
A trigger action that begins a Storyboard. Not commonly used.

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.

TriggerAction object must be associated with one and only one trigger object

I defined BeginStoryboard object in resources in style.
In same style definition I would like use this BeginStoryboard object in 2 event triggers which fire animation.
It is possible that 2 different event triggers will use same object or I must define 2 different BeginStoryboard objects?
<Style x:Key="SerialPoster" TargetType="Border">
<Style.Resources>
<BeginStoryboard x:Key="SerialPosterBeginStoryBoard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX"
From="0"
To="1"
Duration="0:0:2"
AccelerationRatio="1" />
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY"
From="0"
To="1"
Duration="0:0:2"
AccelerationRatio="1" />
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
From="70"
To="0"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</Style.Resources>
<!-- TriggerAction object must be associated with one and only one trigger object. -->
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<EventTrigger.Actions>
<StaticResource ResourceKey="SerialPosterBeginStoryBoard"/>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseEnter">
<EventTrigger.Actions>
<StaticResource ResourceKey="SerialPosterBeginStoryBoard" />
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
Yes, it is possible to reference resource and so to reuse the resource instance at different places.
No need to place the Storyboard inside Style.Resource just place it inside Window.

WPF Animation Relative Values

I am trying to learn about Storyboards and animation in WPF. I have a very simple question which I cannot seem to answer.
I have a rectangle that is placed in a grid. I am trying to move the rectangle from one side of the grid to the other side. I can get the rectangle to move successfully. However the issue is that I'm specifying the From & To values. So in my code below I have hard coded the from (50) & to (300) values. What I want to happen is for the rectangle to go to the other side of the grid without me hard coding a value. Because if a user resizes the window the values I put in will be a waste of time.
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width"
From="50"
To="300"
Duration="0:0:5"/>
<ColorAnimation
Storyboard.TargetProperty="Fill.Color"
To="Yellow"
BeginTime="0:0:5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>
Instead of using the Width property, you could use ScaleTransform of RenderTransform. This will let you scale according to the parent element and not the width itself. See the example underneath and see if it works...
<Rectangle Height="70" Fill="Green">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.2"/>
</TransformGroup>
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
From="0.2"
To="1"
Duration="0:0:5"/>
<ColorAnimation
Storyboard.TargetProperty="Fill.Color"
To="Yellow"
BeginTime="0:0:5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
When animating sizes/locations with Storyboards, always use the ActualWidth and/or Actualheight properties instead of the usual Width and Height properties because the Width and Height properties can often have NaN (Not a number) values which will blow up when the Storyboard tries to access it/them.
For this animation, you'll need to declare the Name property of the parent element because we'll reference it in the Storyboard. Try this and let me know how you get on:
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" From="50"
To="{Binding ActualWidth, ElementName=ParentContainer}" Duration="0:0:5"/>
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="Yellow"
BeginTime="0:0:5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>

Pendulum-like animation in silverlight

Hi I would like to make animation start from the center and then swing like see-saw. Basiclly, it is what I posted in XAML but I cannot get it working.
<Storyboard x:Name="wiggleAnimation" >
<DoubleAnimation Storyboard.TargetName="rotateSlider"
Duration="0:0:1" To="20"
Storyboard.TargetProperty="Angle">
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="rotateSlider"
Duration="0:0:1" To="-20"
RepeatBehavior="Forever"
AutoReverse="True"
Storyboard.TargetProperty="Angle">
</DoubleAnimation>
</Storyboard>
Should I use Keyframes? How after animation starts change the duration of it? Maybe I should use other approach?
What you could do is create a single Animation from -20 to +20, but start the Animation in the middle.
<Storyboard x:Name="wiggleAnimation" >
<DoubleAnimation Storyboard.TargetName="rotateSlider"
Duration="0:0:2" From="-20" To="20"
RepeatBehavior="Forever"
AutoReverse="True"
Storyboard.TargetProperty="Angle">
</DoubleAnimation>
</Storyboard>
And the code to start the animation:
wiggleAnimation.Begin();
wiggleAnimation.Seek(TimeSpan.FromSeconds(1));
Edit:
Alternatively, you can create two animations, targeting two different transforms:
<Button Content="Click" Click="button_Click" RenderTransformOrigin="0.5 0.5" >
<Button.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rotateSlider" />
<RotateTransform x:Name="rotateSlider2" />
</TransformGroup>
</Button.RenderTransform>
</Button>
Now you animate both of the RotateTransforms at the same time:
<Storyboard x:Name="wiggleAnimation"
RepeatBehavior="Forever"
AutoReverse="True"
Duration="0:0:3" >
<DoubleAnimation Storyboard.TargetName="rotateSlider"
Duration="0:0:1" From="0" To="20"
Storyboard.TargetProperty="Angle">
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="rotateSlider2"
Duration="0:0:2" From="0" To="-40"
BeginTime="0:0:1"
Storyboard.TargetProperty="Angle">
</DoubleAnimation>
</Storyboard>
With this approach you do not need to seek the Storyboard to the middle before starting it. Either one of these approaches should enable you to achieve what you are looking to do.
Also, to make the animation look a bit more natural, you probably want to apply an EasingFunction to it.

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!

Categories