Toaster Popup only showing once - c#

I have the following XAML for a "toaster" popup:
<Popup x:Name="popupMessage"
Width="500"
Height="100"
IsOpen="False"
Placement="Top"
PlacementTarget="{Binding ElementName=statusBarMain}"
StaysOpen="True">
<Popup.Style>
<Style>
<Style.Triggers>
<Trigger Property="Popup.IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="0" />
</DoubleAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
<DiscreteBooleanKeyFrame KeyTime="0:0:4" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Popup.Style>
<Popup.RenderTransform>
<ScaleTransform ScaleY="1" />
</Popup.RenderTransform>
<Border Width="504"
Height="104"
BorderBrush="#FF0F3D5C"
BorderThickness="2">
<Border Width="500"
Height="100"
BorderBrush="White"
BorderThickness="2">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFD3CCF5" />
<GradientStop Offset="1" Color="#FF0F3D5C" />
</LinearGradientBrush>
</Border.Background>
<TextBlock x:Name="textBlockMessage"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="18"
Foreground="White"
Text="{Binding NotificationMessage}" />
</Border>
</Border>
</Popup>
The problem with this Popup is that it only seems to work once. I set popupMessage.IsOpen = true and this shows the popup one time. All subsequent calls don't let the popup appear. I checked and the IsOpen property is indeed set to false at the end of the animation.
Clearly I'm missing something here, but what?

You need to stop your storyboard in the ExitActions of your Trigger.
Try this:
<Trigger Property="Popup.IsOpen" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Name="OpenStoryboard">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1" />
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="0" />
</DoubleAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
<DiscreteBooleanKeyFrame KeyTime="0:0:4" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="OpenStoryboard"/>
</Trigger.ExitActions>
</Trigger>
I had a similar issue when changing the background colour of a control using an animation and it would also only work once.

Related

Use MetroProgressBar control animation in a project without Mahapps.Metro assembly

I am trying to use the existing progress animation MetroProgressBar from MahApps.Metro framework only without the framework as a whole.
Here is what I have tried so far:
Added dictionary MetroProgressBar.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test_Tmp"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<System:Double x:Key="MahApps.Sizes.ProgressBar.MinHeight">6</System:Double>
<Style x:Key="MahApps.Styles.MetroProgressBar" TargetType="{x:Type local:MetroProgressBar}">
<Setter Property="Background" Value="#1FFFFFFF" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="red" /> <!-- replace dynamic ressource from mahapps for demo-->
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Maximum" Value="100" />
<Setter Property="MinHeight" Value="{StaticResource MahApps.Sizes.ProgressBar.MinHeight}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MetroProgressBar}">
<ControlTemplate.Resources>
<Storyboard x:Key="IndeterminateStoryboard" RepeatBehavior="Forever">
<DoubleAnimation x:Name="MainDoubleAnim"
Storyboard.TargetName="EllipseGrid"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
Duration="0:0:3.917" />
<DoubleAnimationUsingKeyFrames x:Name="E1Anim"
Storyboard.TargetName="E1"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:3" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames x:Name="E2Anim"
Storyboard.TargetName="E2"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.167" Value="0" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:1.167" />
<EasingDoubleKeyFrame KeyTime="0:0:2.167" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:3.167" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames x:Name="E3Anim"
Storyboard.TargetName="E3"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.333" Value="0" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:1.333" />
<EasingDoubleKeyFrame KeyTime="0:0:2.333" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:3.333" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames x:Name="E4Anim"
Storyboard.TargetName="E4"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:1.5" />
<EasingDoubleKeyFrame KeyTime="0:0:2.5" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:3.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames x:Name="E5Anim"
Storyboard.TargetName="E5"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.667" Value="0" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:1.667" />
<EasingDoubleKeyFrame KeyTime="0:0:2.667" />
<SplineDoubleKeyFrame KeySpline="0.4,0,0.6,1" KeyTime="0:0:3.667" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="B1" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="-50" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="B2" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="-50" />
<EasingDoubleKeyFrame KeyTime="0:0:0.667" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.167" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:3.167" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="B3" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="-50" />
<EasingDoubleKeyFrame KeyTime="0:0:0.833" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.333" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:3.333" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="B4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="-50" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.5" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:3.5" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="B5" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="-50" />
<EasingDoubleKeyFrame KeyTime="0:0:1.167" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.667" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:3.667" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="EllipseGrid"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="DeterminateRoot"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="E1" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="E2" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.167" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.167" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.167" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.167" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="E3" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.333" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.333" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.333" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.333" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="E4" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.5" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.5" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="E5" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.667" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.667" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.667" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:3.667" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="ContainingGrid">
<Grid x:Name="EllipseClip" ClipToBounds="True">
<Grid x:Name="EllipseGrid" Opacity="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RenderTransform>
<TranslateTransform />
</Grid.RenderTransform>
<Border x:Name="B1"
Grid.Column="8"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TranslateTransform />
</Border.RenderTransform>
<Ellipse x:Name="E1"
Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform />
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Rectangle Grid.Column="7" Width="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border x:Name="B2"
Grid.Column="6"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TranslateTransform />
</Border.RenderTransform>
<Ellipse x:Name="E2"
Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform />
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Rectangle Grid.Column="5" Width="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border x:Name="B3"
Grid.Column="4"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TranslateTransform />
</Border.RenderTransform>
<Ellipse x:Name="E3"
Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform />
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Rectangle Grid.Column="3" Width="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border x:Name="B4"
Grid.Column="2"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TranslateTransform />
</Border.RenderTransform>
<Ellipse x:Name="E4"
Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform />
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Rectangle Grid.Column="1" Width="{Binding EllipseOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<Border x:Name="B5"
Grid.Column="0"
RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TranslateTransform />
</Border.RenderTransform>
<Ellipse x:Name="E5"
Width="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Height="{Binding EllipseDiameter, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TranslateTransform />
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</Grid>
</Grid>
<Grid x:Name="DeterminateRoot"
Margin="{TemplateBinding Padding}"
Opacity="0">
<Border x:Name="PART_Track"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" />
<Rectangle x:Name="PART_Indicator"
HorizontalAlignment="Left"
Fill="{TemplateBinding Foreground}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsIndeterminate" Value="False">
<Setter TargetName="DeterminateRoot" Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="MinHeight" Value="0" />
<Setter Property="MinWidth" Value="{StaticResource MahApps.Sizes.ProgressBar.MinHeight}" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter TargetName="ContainingGrid" Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="-90" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Merging dictionary in App.xaml:
<ResourceDictionary Source="Styles/MetroProgressBar.xaml"/>
Also I have added the class MetroProgressBar.cs, which introduced at this line, following error:
bar.Invoke(resetAction);
Error CS1061 'MetroProgressBar' does not contain a definition for 'Invoke' and no accessible extension method 'Invoke' accepting a first argument of type 'MetroProgressBar' could be found (are you missing a using directive or an assembly reference?)
TestWindow.xaml:
<Window x:Class="Test_Tmp.TestWindow" x:Name="win"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test_Tmp"
mc:Ignorable="d"
Title="TestWindow" Height="450" Width="800">
<Grid>
<local:MetroProgressBar IsIndeterminate="True" Foreground="Red" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
</Grid>
</Window>
What do I have to do to correctly implement the required Invoke() method to be able to use MetroProgressBar control?
Unfortunately you need a MetroWindow to show any Dialog shipped with MahApps. That said MahApps is open source, so you can get the code and implement it on your own. Also an integration of MaterialDesign inside a MetroWindow works.

WPF MultiDataTrigger animation incorrect behavior

I need a small square inside a Canvas to be animated depending on View-Model's properties, here's XAML
<Style x:Key="FlashingRectStyle">
<Style.Triggers>
<!-- HasPath & IsBig -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="20" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="20" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="190" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="30" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="115" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="35" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
</MultiDataTrigger>
<!-- HasPath & Not IsBig -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="77" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="73" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="138" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="57" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="97" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="53" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
</MultiDataTrigger>
<!-- Not HasPath-->
<DataTrigger Binding="{Binding Path=HasPath}" Value="False">
<Setter Property="Canvas.Left" Value="105" />
<Setter Property="Canvas.Top" Value="75" />
</DataTrigger>
</Style.Triggers>
</Style>
And usage
<Canvas>
<Rectangle Style="{StaticResource FlashingRectStyle}" Width="30" Height="20" />
</Canvas>
The defaults for HasPath and IsBig are both True and the first animation block "HasPath & IsBig" animates correct.
Also if I change IsBig to false "HasPath & Not IsBig" does begin animating. But if I then change back IsBig to true - nothing happens and "HasPath & Not IsBig" keeps animating. Also if I set HasPath to false it should fire "Not HasPath" but it doesn't. How do I make it switch animation on fly when properties changed?
You need to remove the previous storyboard in the ExitActions before adding a new one:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=HasPath}" Value="True" />
<Condition Binding="{Binding Path=IsBig}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard x:Name="BeginStoryboardName">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="77" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="73" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="138" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Top)"
Duration="0:0:3" RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame Value="57" KeyTime="0:0:0" />
<DiscreteDoubleKeyFrame Value="97" KeyTime="0:0:1" />
<DiscreteDoubleKeyFrame Value="53" KeyTime="0:0:2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="BeginStoryboardName"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>

Animated split-flap display

I'd like to create an animated split-flap display using c# / wpf. I want it to look similar to the one, that can be seen in this video, but without the 3D effect. As I don't have a lot experience with wpf, I'd like to know how I can implement a UserControl for a single animated letter.
Without 3d, you could do this with multiple images.
Idea #1 Think animated gif. Only, you would have a one set of images to flip from 1 to 2. Another set of images to flip from 2 to 3, etc...
See Option 2 at this site:
http://www.wpfsharp.com/2011/05/11/wpf-replacement-options-for-an-animated-gif
Then you would have the click start the storyboard, then end at a new image instead of the same image. The more images you have, the less choppy it will be.
Idea #2
My other idea would use a top and bottom image for each number. Bend the images with RenderTransform changes.
Give this a look. I got it halfway there for you:
<Window.Resources>
<Storyboard x:Key="FlipNumberStoryBoard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)" Storyboard.TargetName="Img1Top">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="10"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="20"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="35"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="60"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="75"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="88"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="Img1Top">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="-2.01"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="-3.45"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="-5.55"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="-7"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-8.75"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="-9.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="-8.25"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Img1Top">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0.90"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0.80"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.60"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0.40"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0.20"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="0.10"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.01"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="Img1Top">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="2.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="10.1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="20"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="22.6"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="24.9"/>
</DoubleAnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)" Storyboard.TargetName="Img2Bottom">
<EasingInt32KeyFrame KeyTime="0:0:0.8" Value="1"/>
</Int32AnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Img1Top">
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)" Storyboard.TargetName="Img2Bottom">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="-88"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="-75"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-60"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="-35"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="-20"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="-10"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="-5"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Img2Bottom">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="0.01"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="0.10"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.20"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="0.40"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0.60"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="0.80"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="0.90"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="Img2Bottom">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="-9.121"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="-8.87"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-8.564"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="-7"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="-5.438"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="-3.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="-2.001"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="Img2Bottom">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="-24.75"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="-22.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-20.062"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="-15.062"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="-10"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="-5.062"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="-2.562"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Img2Bottom">
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image x:Name="Img2Top" Source="Images/02top.png" Grid.Row="1" Width="70" Height="50" RenderTransformOrigin="0.5,0.5" Margin="0,-1,0,0"/>
<Image x:Name="Img1Top" Source="Images/01top.png" Grid.Row="1" Width="70" Height="50" RenderTransformOrigin="0.5,0.5" Margin="0,-1,0,0">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<Image x:Name="Img2Bottom" Source="Images/02.png" Grid.Row="2" Width="70" Height="50" Visibility="Collapsed" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<Image x:Name="Img1Bottom" Source="Images/01.png" Grid.Row="2" Width="70" Height="50" RenderTransformOrigin="0.5,0.5"/>
<Button Content="Next" HorizontalAlignment="Left" Margin="223.5,5,0,0" Grid.Row="3" VerticalAlignment="Top" Width="70" Click="Button_Click" />
</Grid>
And then on click of the button, you can see the flip.
using System.Windows;
using System.Windows.Media.Animation;
namespace RenderTransformExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var storyboard = (Storyboard)this.Resources["FlipNumberStoryBoard"];
storyboard.Begin();
}
}
}
Now hooking that up so it just loops through images is up to you.
You can use ScaleTransform to achieve the animation, and some dependency properties to make the UserControl easy to use.
First, you have to display your letter in two halves, which can be done using these styles :
<Style x:Key="UpperHalf" TargetType="ContentControl">
<Style.Setters>
<Setter Property="FontFamily" Value="Courier New" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="RenderTransformOrigin" Value="0.5,1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Height="{Binding ElementName=SizeRef,
Path=ActualHeight,
Converter={StaticResource HalfConverter}}"
VerticalAlignment="Top"
Background="{TemplateBinding Background}"
CornerRadius="10,10,0,0"
Padding="10,0">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<Style x:Key="LowerHalf" TargetType="ContentControl">
<Style.Setters>
<Setter Property="FontFamily" Value="Courier New" />
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="RenderTransformOrigin" Value="0.5,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Height="{Binding ElementName=SizeRef,
Path=ActualHeight,
Converter={StaticResource HalfConverter}}"
VerticalAlignment="Bottom"
Background="{TemplateBinding Background}"
CornerRadius="0,0,10,10"
Padding="10,0">
<ContentPresenter Content="{TemplateBinding Content}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock VerticalAlignment="Bottom" Text="{Binding}" />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
Then to display two overlapping letters (the old one and the new one) :
<Grid>
<!-- Hidden textblock, only used for measurement purpose -->
<!-- The border is here to set the total height of the display so that we can have a small space between the two halves -->
<Border Margin="0,1" Visibility="Hidden">
<TextBlock Name="SizeRef"
Margin="10,0"
FontFamily="Courier New"
Text="{Binding ElementName=Root,
Path=Letter}" />
</Border>
<ContentControl Name="Letter1Top"
Background="Gray"
Content="{Binding ElementName=Root,
Path=Letter1}"
Style="{StaticResource UpperHalf}">
<ContentControl.RenderTransform>
<ScaleTransform />
</ContentControl.RenderTransform>
</ContentControl>
<ContentControl Name="Letter2Top"
Background="Gray"
Content="{Binding ElementName=Root,
Path=Letter2}"
Style="{StaticResource UpperHalf}">
<ContentControl.RenderTransform>
<ScaleTransform />
</ContentControl.RenderTransform>
</ContentControl>
<ContentControl Name="Letter1Bottom"
Background="Gray"
Content="{Binding ElementName=Root,
Path=Letter1}"
Style="{StaticResource LowerHalf}">
<ContentControl.RenderTransform>
<ScaleTransform />
</ContentControl.RenderTransform>
</ContentControl>
<ContentControl Name="Letter2Bottom"
Background="Gray"
Content="{Binding ElementName=Root,
Path=Letter2}"
Style="{StaticResource LowerHalf}">
<ContentControl.RenderTransform>
<ScaleTransform />
</ContentControl.RenderTransform>
</ContentControl>
</Grid>
The properties used above are created in code behind :
public partial class SplitFlapLetter
{
public SplitFlapLetter()
{
InitializeComponent();
}
public char Letter
{
get { return (char)GetValue(LetterProperty); }
set { SetValue(LetterProperty, value); }
}
public static readonly DependencyProperty LetterProperty =
DependencyProperty.Register("Letter", typeof(char), typeof(SplitFlapLetter), new UIPropertyMetadata(OnLetterChanged));
private char Letter1
{
get { return (char)GetValue(Letter1Property); }
set { SetValue(Letter1Property, value); }
}
public static readonly DependencyProperty Letter1Property =
DependencyProperty.Register("Letter1", typeof(char), typeof(SplitFlapLetter), new UIPropertyMetadata(null));
private char Letter2
{
get { return (char)GetValue(Letter2Property); }
set { SetValue(Letter2Property, value); }
}
public static readonly DependencyProperty Letter2Property =
DependencyProperty.Register("Letter2", typeof(char), typeof(SplitFlapLetter), new UIPropertyMetadata(null));
private bool _isLetter1Active;
private static void OnLetterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var uc = d as SplitFlapLetter;
if (uc == null) return;
if (uc._isLetter1Active)
uc.Letter2 = uc.Letter;
else
uc.Letter1 = uc.Letter;
var sb = uc.FindResource(uc._isLetter1Active ? "GotoLetter2Animation" : "GotoLetter1Animation") as Storyboard;
if (sb != null) sb.Begin();
uc._isLetter1Active = !uc._isLetter1Active;
}
private readonly List<char> _letters = new List<char> { 'A', 'B', 'C', 'D', 'E' };
private void OnClick(object sender, MouseButtonEventArgs e)
{
Letter = _letters[(_letters.IndexOf(Letter) + 1) % _letters.Count];
}
}
The Letter property is the only public one and there is a listener on its changes.
This listener sets Letter1 or Letter2 to the new value, changing at every run, so that the other property is still set to the old value.
It then starts one of the two storyboard defined in the UserControl resources :
<Storyboard x:Key="GotoLetter1Animation">
<DoubleAnimation Duration="0:0:0"
Storyboard.TargetName="Letter1Bottom"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="0" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter2Bottom"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter1Bottom"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<DoubleAnimation Duration="0:0:0.2"
From="1"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="0" />
<DoubleAnimation BeginTime="0:0:0.2"
Duration="0:0:0.2"
From="0"
Storyboard.TargetName="Letter1Bottom"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="1" />
<Int32Animation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<Int32Animation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<DoubleAnimation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="1" />
</Storyboard>
<Storyboard x:Key="GotoLetter2Animation">
<DoubleAnimation Duration="0:0:0"
Storyboard.TargetName="Letter2Bottom"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="0" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter1Bottom"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<Int32Animation Duration="0:0:0"
Storyboard.TargetName="Letter2Bottom"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<DoubleAnimation Duration="0:0:0.2"
From="1"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="0" />
<DoubleAnimation BeginTime="0:0:0.2"
Duration="0:0:0.2"
From="0"
Storyboard.TargetName="Letter2Bottom"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="1" />
<Int32Animation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter2Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="2" />
<Int32Animation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Panel.ZIndex)"
To="1" />
<DoubleAnimation BeginTime="0:0:0.4"
Duration="0:0:0"
Storyboard.TargetName="Letter1Top"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)"
To="1" />
</Storyboard>
There's probably some way to reduce this xaml and use only one storyboard that would uses the appropriate targets.
I think that this project could really give you a base for what you want to do.
Unfortunately, I don't see how this split-flap display could look well without 3D.
Good luck !

Need to transform a rectangle's color in Windows Phone 7

I have a rectangle, and I have a storyboard:
<Storyboard x:Key="PressAndHoldColorBar">
<ColorAnimationUsingKeyFrames Duration="0:0:10" FillBehavior="Stop" Storyboard.TargetName="rectWarning" Storyboard.TargetProperty="Fill">
<LinearColorKeyFrame KeyTime="0:0:0" Value="Green" />
<LinearColorKeyFrame KeyTime="0:0:7" Value="Yellow" />
<LinearColorKeyFrame KeyTime="0:0:10" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Rectangle Height="100" HorizontalAlignment="Left" Margin="12,328,0,0" Name="rectWarning" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="200">
I want this color change to occur when another button is pressed, so I'm trying to call the code programmatically:
s = (Storyboard)this.Resources["PressAndHoldColorBar"];
s.Begin();
I've narrowed it down to Storyboard.TargetName and TargetProperty in the first snippet (I think). I just need help figuring out what to do to get it to work completely.
Figured it out:
<Storyboard x:Name="PressAndHoldColorBar">
<ColorAnimationUsingKeyFrames Duration="0:0:10" FillBehavior="Stop" Storyboard.TargetName="rectWarning"
Storyboard.TargetProperty="(Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="0:0:0" Value="Green" />
<LinearColorKeyFrame KeyTime="0:0:7" Value="Yellow" />
<LinearColorKeyFrame KeyTime="0:0:10" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
You have to use (Fill).(SolidColorBrush.Color). It doesn't like (Shape.Fill).

How to edit a StoryBoard to put it in a Button Style?

I've created a storyboard for a button in blend that I want it to apply everytime the button is pressed, So I tried to create a style,I've been stucked for a long time now.
here is the code of my Storyboard:
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0"
Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.25"
Value="0.85">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.5"
Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0"
Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.25"
Value="0.85">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.5"
Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<QuarticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
And Here is the code of my button style:
<Style x:Key="ParametersButton"
TargetType="ButtonBase">
<Setter Property="Background"
Value="{StaticResource TransparentBrush}" />
<Setter Property="BorderBrush"
Value="{StaticResource PhoneForegroundBrush}" />
<Setter Property="Foreground"
Value="{StaticResource PhoneForegroundBrush}" />
<Setter Property="MinHeight"
Value="72" />
<Setter Property="BorderThickness"
Value="{StaticResource PhoneDefaultBorderThickness}" />
<Setter Property="FontFamily"
Value="{StaticResource PhoneFontFamilyNormal}" />
<Setter Property="FontSize"
Value="{StaticResource PhoneFontSizeMediumLarge}" />
<Setter Property="Padding"
Value="0,15,15,0" />
<Setter Property="Height"
Value="72" />
<Setter Property="Width"
Value="72" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="UnPressed" />
<VisualState x:Name="Pressed">
<Storyboard>
<!--Here is where I want to insert my StoryBoard-->
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
CornerRadius="0"
Background="#FF1BA1E2"
Margin="{StaticResource PhoneTouchTargetOverhang}"
RenderTransformOrigin="0.5,0.5">
<ContentControl x:Name="foregroundContainer"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
FontSize="{TemplateBinding FontSize}"
Padding="{TemplateBinding Padding}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I proceed ?
Thanks,
Renaud
It is easiest in Expression Blend, when editing your style, select the visual stater you want, open the storyboard panel and create your animation. This will trigger when you go to that state.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:00"
Value="White" />
<EasingColorKeyFrame KeyTime="00:00:01"
Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Categories