How to control a storyboard animation from C# and XAML - c#

There's a lot of questions around this on the net, but after reading them, and the MS docs on animation control, I'm unable to mimic storyboard control from XAML event triggers in C# code.
In this XAML file, I have a canvas that I am rotating. I'd like to add interactivity to the rotation,
<Window x:Class="GraphicsBook.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:k="clr-namespace:GraphicsBook;assembly=Testbed2D"
Title="2D Testbed"
KeyDown="KeyDownHandler"
Height="600"
Width="600" >
<DockPanel LastChildFill="True">
<StackPanel x:Name="stack" DockPanel.Dock ="Top" Orientation="Vertical" Background="#ECE9D8">
<Button Name="StartAnimationClick">Start animation</Button>
<Button Name="StopAnimationClick" Click="stopAnimationClick">Stop animation</Button>
<Canvas x:Name="Grid">
<Canvas.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="CanvasRotation" CenterX="300" CenterY="300" Angle="0"/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="StartAnimationClick">
<BeginStoryboard Name="GridRotationStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="CanvasRotation"
Storyboard.TargetProperty="Angle"
From="0.0" To="360.0"
Duration="00:00:10.00" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<!--<EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimationClick">
<StopStoryboard BeginStoryboardName="GridRotationStoryboard"/>
</EventTrigger>-->
</StackPanel.Triggers>
</StackPanel>
</DockPanel>
</Window>
The commented event trigger,
<!--<EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimationClick">
<StopStoryboard BeginStoryboardName="GridRotationStoryboard"/>
</EventTrigger>-->
Does indeed work as expected, that is, if I click the button, the animation stops. However, the version of the XAML above tries to replicate this functionality in C#, but this doesn't work. The click handler looks like this,
private void stopAnimationClick(object sender, RoutedEventArgs e)
{
Debug.Print("Stop animation");
// ???
}
I'm unable to control the animation object in ???, not matter what technique I try to get a handle on it. I must be plumbing the pieces incorrectly somehow, but I can't see what is wrong.

You can mimic what the EventTrigger does by calling BeginAnimation with a second argument of null:
private void stopAnimationClick(object sender, RoutedEventArgs e)
{
CanvasRotation.BeginAnimation(RotateTransform.AngleProperty, null);
}

Related

How to make text moving Animation from bottom to top in UWP

How to animate the text from bottom to top in UWP. Is there any better way to trigger style properties in UWP.
How to make text moving Animation from bottom to top in UWP
You could use DoubleAnimation to approach, Please refer the following code.
<Grid>
<Grid.Resources>
<Storyboard x:Name="MoveStoryboard">
<DoubleAnimation Storyboard.TargetName="Tbk"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
From="0" Windows10version1903:To="{x:Bind TbkY, Mode=TwoWay}" Duration="0:0:2">
</DoubleAnimation>
</Storyboard>
</Grid.Resources>
<TextBlock Loaded="Tbk_Loaded"
Name="Tbk"
Text="hello Nico"
VerticalAlignment="Bottom"
Visibility="Visible"
HorizontalAlignment="Center"
FontSize="22"
TextLineBounds="Full" >
<TextBlock.RenderTransform>
<CompositeTransform/>
</TextBlock.RenderTransform>
</TextBlock>
<Button Content="Move" Click="Button_Click"/>
</Grid>
Code Behind
private void Button_Click(object sender, RoutedEventArgs e)
{
MoveStoryboard.Begin();
}
public double TbkY { get; set; }
private void Tbk_Loaded(object sender, RoutedEventArgs e)
{
TbkY = -Tbk.ActualOffset.Y;
}
MVVM aproach to trigger story bord on datachange
We can also trigger the story board on Data change. I tried the below code its works for me. Use the below namespace before going to start . The nuget package will be availble on the link Microsoft.Xaml.Behaviors.Uwp.Managed
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media ="using:Microsoft.Xaml.Interactions.Media"
<Page.Resources>
<Storyboard x:Name="MoveStoryboard">
<DoubleAnimation Storyboard.TargetName="txttext1"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
From="0" To="-200" Duration="0:0:2">
</DoubleAnimation>
</Storyboard>
</Page.Resources>
<Grid>
<TextBlock Text="Sample text to Animate">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding ={Binding AnimateText} Value = true>
<Media:ControlStoryboardAction Storyboard="{StaticResource MoveStoryboard}"/>
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<TextBlock.RenderTransform>
<CompositeTransform/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
I have changed the AnimateText property in ViewModel. Whenever the property value is changed .The textblock will move bottom to top based on(- Y value that is To="-200").

EventTriggers on an Image

I have a set of Images in a GridView, and the images are not able to load instantly when the page is opened. So, to create a smoother transition, I am trying to use an EventTrigger in the Image to animate the opacity from 0 to 1 when the image loads, like so:
<GridView.ItemTemplate>
<DataTemplate>
<Border Background="{ThemeResource ButtonBackground}" HorizontalAlignment="Stretch" MaxWidth="300" MinWidth="200">
<Image Source="{Binding SmallUri}" Stretch="UniformToFill"
Opacity="0" ToolTipService.ToolTip="{Binding Author.Name}">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.ImageOpened">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.25" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
But whenever the page attempts to load, it crashes with the error:
Failed to assign to property 'Windows.UI.Xaml.EventTrigger.RoutedEvent'
Why does this not work? It also fails if I change the RoutedEvent property to Loaded, FrameworkElement.Loaded, Image.Loaded, or any other value I could think of. I would like a solution that does not involve having to write a custom control / codebehind.
But whenever the page attempts to load, it crashes with the error "Failed to assign to property 'Windows.UI.Xaml.EventTrigger.RoutedEvent'." Why does this not work?
As #Clemens said, problem is in Windows Runtime XAML, the default behavior for event triggers and the only event that can be used to invoke an EventTrigger is FrameworkElement.Loaded.
I'm writing this answer here to call another problem of your code, as you said:
It also fails if I change the RoutedEvent property to Loaded, FrameworkElement.Loaded, Image.Loaded
This is because you didn't specify the Storyboard.TargetName in your DoubleAnimation, it will throw the exception when it runs. To solve this problem, you will need to give a name to your Image in the DataTemplate and modify your storyboard like this:
<Image x:Name="myImage" Source="{Binding SmallUri}" Stretch="UniformToFill">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="00:00:5" Storyboard.TargetName="myImage" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
From the Remarks section on the EventTrigger page on MSDN:
If you do choose to use Triggers, in Windows Runtime XAML, the default
behavior for event triggers and the only event that can be used to
invoke an EventTrigger is FrameworkElement.Loaded. Because that's both
the default and the only enabled behavior, don't set the RoutedEvent
attribute. Just use the XAML <EventTrigger>. For more info, see
Triggers.
I know it's too late for answering the question but for those who will be having the same issue.
you can use this XAML code:
<Image x:Name="TumbImage" Opacity="0" ...>
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ImageOpened">
<media:ControlStoryboardAction Storyboard="{StaticResource ImageOpacityStoryBoard}" ControlStoryboardOption="Play"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
The Sample storyboard I used here:
<Storyboard x:Key="ImageOpacityStoryBoard">
<DoubleAnimation Storyboard.TargetName="TumbImage"
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:0.33" />
</Storyboard>
and the XML namespaces used:
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:media="using:Microsoft.Xaml.Interactions.Media"

WPF: Deactivating the button animations

I'm designing an UI atm and have the problem that the button animations don't fit the style of my Program and I would rather just change the colour.
My problem is: I just cant find a way do deactivate the animation that appears when you hover about or click a button :(
Is it even possible ?
Here is an image animation which is similar to an Button.
<Image Width="20" Height="20" Source="image\close.png"
ToolTip="close"
Opacity="0.5" Canvas.Left="720" Canvas.Top="3"
MouseLeftButtonDown="Close_MouseLeftButtonDown">
<Image.RenderTransform>
<RotateTransform x:Name="imgTransform"
CenterX="10"
CenterY="10"
Angle="0"/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseEnter">
<BeginStoryboard HandoffBehavior="Compose" >
<Storyboard Name="myStoryBoard" >
<DoubleAnimation
Storyboard.TargetName="imgTransform"
Storyboard.TargetProperty="Angle"
By="90" Duration="0:0:.2"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image>
image\close.png is my image and you can change into yours.
As you can test,it has a duration and will stop automatically.However you can get StoryBoard Object by its Name property in C# code and call Stop method on it.

Changing property of other element on button "click" event (WPF)

I want to create a toggle button which gives rise to a rectangular panel on clicking. Since rectangle is not having click property so I have enclosed it in a button. Please provide me further guidance.
<Window x:Class="AnimatedRectangle.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" BorderBrush="Black" BorderThickness="2" Foreground="White" VerticalAlignment="Stretch" WindowStartupLocation="CenterScreen">
<Grid>
<Button Name="MyButton">
<Button.Template>
<ControlTemplate>
<Rectangle
Name="MyRectangle"
Width="150"
Height="30"
Fill="Cyan"
Margin="0,220,0,0">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
Please visualize it this way : Both the rectangle and button are of same width and initially the button overlaps(or hide in any other way)the rectangle. When the button is clicked then the rectangle appears and it looks like the rectangular body is part of a button.
JUST LIKE we press downward symbol in address bar and the history/suggestions appears in rectangular body. But here I want a button to give rise to a rectangle body rather than a downward symbol like in address bar.
StackOverflow is not letting me post images as I need to have 10 reputation posts :(
Thanks a lot..!!

how to move UI element with storyboard?

I've worked with Opacity property in storyboard
but I cant figure it out how to move an UI element like grid stackpanel button ..... in c#?
(I am writing the storyboard in c# not in xaml )
Well, that depends on your actual layout: Do you want to animate a button in a Grid or in a Canvas (could animate the Margin property or the Canvas.Left attached property, respectively)? Do you want to animate the property itself or a transform (the latter would animate a RenderTransform - specifically a TranslateTransform). You would use the RenderTransform if you still want to refer to the "old" position.
One simple way is:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="myButton"
Storyboard.TargetProperty="(Canvas.Left)" From="1" To="350"
Duration="0:0:10" BeginTime="0:0:0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Canvas x:Name="myCanvas" Background="Yellow">
<Button x:Name="myButton" Width="100" Height="30" Canvas.Left="100" Canvas.Top="100" />
</Canvas>
</Grid>
</Window>
it would be better if you use blend for storyboard ..i have genrated a code for stackpanel movement towards right ..just check it..
you can go through this video aslo it's very good it will perfectly work in your case
<Page.Resources>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="hello">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="100"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Name="hello" Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" >
<StackPanel.RenderTransform>
<CompositeTransform/>
</StackPanel.RenderTransform>
<TextBlock Text="hello1" FontSize="50" />
<Button Content="Button" FontSize="50" Click="Button_Click_1" />
</StackPanel>
</Grid>
and to start do this on button click..
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Storyboard1.Begin();
}
for better understand just read about how to use blend..

Categories

Resources