Place storyboard in style or datatemplate - c#

I have a storyboard that animates an image's width. I created the animation with expression blend:
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(FrameworkElement.Width)"
Storyboard.TargetName="imageFoo">
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="335">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
The problem is that I want to assign that storyboard to all the images in my application not just for the image imageFoo. I will like to start that animation when the MouseEnters an image. How can I do that?

You need to remove the Target name from the storyboard and also move the trigger into a style, there is no code behind required to do this thankfully
In your App.xaml file (or in any resources collection).
<Application.Resources>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)">
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="335">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Application.Resources>
By declaring a style with no x:Key and simply giving a TargetType you're basically telling WPF that it's supposed to apply to every single element in the visual tree with that type.

Related

I cannot stop Storyboard Animation (C# & XAML)

I have the following XAML Code:
<Window.Resources>
<Storyboard x:Key="IconFileChangeColor">
<ColorAnimationUsingKeyFrames Storyboard.TargetName="colorFile" Storyboard.TargetProperty="Color" RepeatBehavior="Forever" AutoReverse="True">
<EasingColorKeyFrame KeyTime="0" Value="#FF690000"/>
<EasingColorKeyFrame KeyTime="0:0:1.5" Value="#FFC33939"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent= "FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource IconFileChangeColor}" />
</EventTrigger>
</Window.Triggers>
C# Code that should stop the animation:
Storyboard fileAnimation = (Storyboard)TryFindResource("IconFileChangeColor");
fileAnimation.Stop();
The Animation starts up fine. However if I execute the C# Code it does not stop the animation... Does anybody know why?

Animation lost when clicking on DataGrid

I have a DataGrid which contains a list of item that implement a boolean property called ResultChanged, this property allow me to create a blink effect on a particular cell of the DataGrid, in particular, if the property is setted to true then the cell of the DataGrid will colored by orange and blinking for 5 seconds, at the end of the animation, the color will keeped on the DataGrid and this working well for me, except for one problem.
Problem
When I click on the DataGrid (any rows) the color applied by the animation will be removed, but I want that such color remain on the cell.
This is my code:
<DataGridTextColumn Header="{DynamicResource hour}" Binding="{Binding Result}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource MaterialDesignDataGridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<Storyboard x:Name="Blink"
AutoReverse="True"
RepeatBehavior="5x">
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01"
Value="Orange" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01"
Value="Black" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Storyboard AutoReverse="False">
<ColorAnimationUsingKeyFrames BeginTime="00:00:10" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:01" Value="Orange" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
someone know what I did wrong?
The animation's effects will be lost when you select or unselect the row affected by the animation, because DataGrid changes the foreground and background brushes of the selected row. Now, normally, the animation's changes to the Foreground and Background properties would have precedence over those changes for the selected row.
But your animation does not animate Foreground and Background! Instead, it animates Foreground.Color and Background.Color; these changes have no precedence and will be lost when something else changes Foreground or Background directly.
Therefore, your animation must animate Foreground and Background directly. Then, the changes will remain in effect even after the animation has ended.
You could achieve this, for example, by using the BrushAnimation class from the answer in question Brush to Brush Animation and using a storyboard similar to this:
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<Storyboard x:Name="Blink"
RepeatBehavior="5x">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:0.5" From="White" To="Orange" />
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:0.5" From="Yellow" To="Black" />
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
EDIT:
Here is a solution that allows AutoReverse to be set to true:
<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- The next two animations will take 10 seconds: -->
<Storyboard x:Name="Blink" AutoReverse="True" RepeatBehavior="5x">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
</Storyboard>
<!-- Same animations as above, but BeginTime offset by 10 seconds and neither repeat nor auto reverse: -->
<Storyboard x:Name="finalBlink" BeginTime="00:00:10">
<local:BrushAnimation Storyboard.TargetProperty="Background"
BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
<local:BrushAnimation Storyboard.TargetProperty="Foreground"
BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
</Storyboard>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>

Canvas not suppported in WPF project?

I'm trying to animate a canvas in WPF using Storyboard and DoubleAnimationsUsingKeyFrames my code goes something like this:
<Canvas x:Name="bgCanvas" Height="261" Canvas.Top="-262" Width="720">
<Canvas.Background>
<ImageBrush ImageSource="Resources/backgroundBlurred.png" Stretch="UniformToFill"/>
</Canvas.Background>
<Canvas.Resources>
<Storyboard x:Key="bgAnim" x:Name="bgAnim">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(bgCanvas.Opacity)" Storyboard.Target="bgCanvas">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Canvas.Resources>
I'm also using Mahapps.Metro for the project. <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(bgCanvas.Opacity)" Storyboard.Target="bgCanvas"> is underlined by blue lines and the error reads:
bgCanvas is not supported in a Windows Presentation Format (WPF) Application.
I'm not sure whats wrong with the code.
BONUS: Is this the right way to animate a canvas in WPF?
Sorry for the nub questions.
You could start the animation in an EventTrigger on the Loaded event of the Canvas:
<Canvas ...>
<Canvas.Background>
<ImageBrush .../>
</Canvas.Background>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
Replace (bgCanvas.Opacity) with (Canvas.Opacity)

Storyboard inside of a DataTrigger not triggering more than once on RaisePropertyChanged event

I am using the MVVM model.
I have a dependency property, a boolean, called "ResultOfUpdate". It is changed whenever a user tries to run a command.
In the setter for this dependency property I am calling "RaisePropertyChanged()" method on the property name.
It is bound to a DataTrigger like so :
<DataTrigger Binding="{Binding ResultOfUpdate}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Opacity)"
AutoReverse="True">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.1" Value="0.1"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.2" Value="0.2"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.3" Value="0.3"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.4" Value="0.4"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.5" Value="0.5"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.6" Value="0.6"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.7" Value="0.7"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.8" Value="0.8"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.9" Value="0.9"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
...
<TextBlock Style="{StaticResource statusStyle}"
Opacity="0" Text="Results updated!"
FontSize="10" FontFamily="Segoe UI"/>
I would like for each time this bool is set to true, the storyboard is played.
Confusingly, this storyboard is then triggered correctly the first time the user runs the command, updating the dependecy property to true.
Subsequent attempts have found that the dependency property setter code is entered, and the RaisePropertyChanged() method called - but the storyboard is not played again.
What have I done incorrectly here ?
You could possibly use an event trigger like this:
<StackPanel>
<TextBlock Text="I'm a text block" Name="theTextBlock"/>
<Button Name="BeginButton">Begin</Button>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="theTextBlock"
Storyboard.TargetProperty="(TextBlock.Opacity)"
From="0.0" To="1.0" AutoReverse="True" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>

Animating UserControl XAML

I have been trying to animate the opening of a UserControl with no luck and was wondering if anyone could help?
I have a UserControl which simply holds information about a record. It opens up as a box on an existing page, however I would like the box to open with a simple animation. I'm trying to get the box to open with an expanding animation instead of the box just appearing.
Below is the code I have been working on.
<UserControl Name="RecordViewerUserControl"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
x:Class="VisionWare.MasterDataServices.Silverlight.UI.Common.RecordViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:conv="clr-namespace:VisionWare.MasterDataServices.Silverlight.UI.Converters"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
Height="490"
Width="600"
Margin="0,0,0,0">
<UserControl.Resources>
<conv:DateConverter x:Key="dateConverter" />
<conv:BoolToVisibilityConverter x:Key="visibilityConverter" />
<conv:EntityIdToUrlConverter x:Key="urlConverter"/>
<conv:FileConverter x:Key="fileConverter"/>
<conv:AlertImageURLConverter x:Key="alertConverter"/>
<Style TargetType="UserControl" x:Key="CustomUserControlStyle">
<Setter Property="Effect">
<Setter.Value>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleX">
<SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="1.05" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleY">
<SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="1.05" />
<SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
I have changed my code according to #jrb 's advice...]
<UserControl.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="RecordViewerUserControl" Storyboard.TargetProperty="Width" To="600"/>
<DoubleAnimation Storyboard.TargetName="RecordViewerUserControl" Storyboard.TargetProperty="Height" To="490"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</UserControl.Triggers>
I have inserted this just after the initial UserControl opening tag.
It is not complaining anymore when the app is run, however it doesn't seem to be having an effect.
Any ideas? Am I missing something in the code behind?
I think your animation values are wrong, in the end you should have a value of 1 (100% size) not 0.
Why do you animate on the first child of LayoutRoot? You should have RecordViewerUserControl as animation target instead.
I suggest you test setting the size on the usercontrol to 1 then use event trigger loaded (i think) and a simple doubleanimation to increase the size of the control.
<EventTrigger RoutedEvent="Loaded">
This is a working example, you can test it in kaxaml.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="1"
Height="1"
Background="Black">
<Page.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Width"
To="200"/>
<DoubleAnimation
Storyboard.TargetProperty="Height"
To="200"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Page.Triggers>
<Grid>
</Grid>
</Page>

Categories

Resources