WPF Countdown text storyboard - wpf

Is it possible to have a Storyboard in Button's style that would show a text countdown as Button content? I.e. button initially appears with content = "OK (20)". And then automatically countdown starts, changing content to "OK (19)", "OK (18)", ..., "OK (0)", without any code in the ViewModel?

With property in VM you can do it more easy and properly.
Without changing VM you can animate text but need to think how to handle event when storyboard will be completed.
<Button Name="myAnimatedButton" Margin="200"
FontSize="16pt" FontFamily="Verdana">Some Text
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames
Storyboard.TargetName="myAnimatedButton" Storyboard.TargetProperty="(Button.Content)"
Duration="0:0:20" FillBehavior="HoldEnd">
<DiscreteStringKeyFrame Value="OK (20)" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="OK (19)" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="OK (18)" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value="OK (17)" KeyTime="0:0:3" />
<DiscreteStringKeyFrame Value="OK (16)" KeyTime="0:0:4" />
<DiscreteStringKeyFrame Value="OK (15)" KeyTime="0:0:5" />
<DiscreteStringKeyFrame Value="OK (14)" KeyTime="0:0:6" />
<DiscreteStringKeyFrame Value="OK (13)" KeyTime="0:0:7" />
<DiscreteStringKeyFrame Value="OK (12)" KeyTime="0:0:8" />
<DiscreteStringKeyFrame Value="OK (11)" KeyTime="0:0:9" />
<DiscreteStringKeyFrame Value="OK (10)" KeyTime="0:0:10" />
<DiscreteStringKeyFrame Value="OK (09)" KeyTime="0:0:11" />
<DiscreteStringKeyFrame Value="OK (08)" KeyTime="0:0:12" />
<DiscreteStringKeyFrame Value="OK (07)" KeyTime="0:0:13" />
<DiscreteStringKeyFrame Value="OK (06)" KeyTime="0:0:14" />
<DiscreteStringKeyFrame Value="OK (05)" KeyTime="0:0:15" />
<DiscreteStringKeyFrame Value="OK (04)" KeyTime="0:0:16" />
<DiscreteStringKeyFrame Value="OK (03)" KeyTime="0:0:17" />
<DiscreteStringKeyFrame Value="OK (02)" KeyTime="0:0:18" />
<DiscreteStringKeyFrame Value="OK (01)" KeyTime="0:0:19" />
<DiscreteStringKeyFrame Value="OK (0)" KeyTime="0:0:20" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Related

WPF Animate different control after first animation is over

I'm animating text in StatusBarItem (from right to left and then Opacity two times).
When this animation finishes It would like to show a button which is in a different StatusBarItem and is set to Visibility.Hidden by default.
How can I do this in XAML?
My XAML - error is "A storyboard tree in a Style cannot specify a TargetName":
<StatusBarItem x:Name="Stat_info" DockPanel.Dock="Right" FontStyle="Italic" Height="23" Foreground="#FFB41414" FontWeight="Bold" Visibility="Hidden">
<StatusBarItem.Style>
<Style TargetType="{x:Type StatusBarItem}">
<Style.Resources>
<Storyboard x:Key="flashAnimate">
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="Content" >
<DiscreteStringKeyFrame Value="T" KeyTime="0:0:0.3" />
<DiscreteStringKeyFrame Value="Te" KeyTime="0:0:0.6" />
<DiscreteStringKeyFrame Value="Tes" KeyTime="0:0:0.9" />
<DiscreteStringKeyFrame Value="Test" KeyTime="0:0:1.2" />
</StringAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" AutoReverse="True" BeginTime="0:0:1.4" Duration="0:0:2.0" RepeatBehavior="0:0:5.4" />
<!--This is a button that should be set to visible-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Btn_info" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:5.5" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName= Stat_info, Path= IsVisible}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<DataTrigger.EnterActions>
<BeginStoryboard Name="flash" Storyboard="{StaticResource flashAnimate}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="flash"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StatusBarItem.Style>
</StatusBarItem>
EDIT:
I've tried provided answer from link, but I can't get It to work. I tried with & without TargetName and just for first animation. Result is no error & no animation :
<Window.Resources>
<ControlTemplate x:Key="StatusBarItemControlTemplate1" TargetType="{x:Type StatusBarItem}">
<ControlTemplate.Resources>
<Storyboard x:Key="myAnimation" Storyboard.TargetName="Stat_info">
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="Content" >
<DiscreteStringKeyFrame Value="T" KeyTime="0:0:0.3" />
<DiscreteStringKeyFrame Value="Te" KeyTime="0:0:0.6" />
<DiscreteStringKeyFrame Value="Tes" KeyTime="0:0:0.9" />
<DiscreteStringKeyFrame Value="Test" KeyTime="0:0:1.2" />
</StringAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Stat_info" From="1" To="0" AutoReverse="True" BeginTime="0:0:1.4" Duration="0:0:2.0" RepeatBehavior="0:0:5.4" />
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName= Stat_info, Path= IsVisible}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="beginAnimation" Storyboard="{StaticResource myAnimation}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="beginAnimation" />
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
<!-- Content to be animated goes here -->
</ControlTemplate>
</Window.Resources>
<StatusBarItem x:Name="Stat_info" Visibility="Hidden" Template="{StaticResource StatusBarItemControlTemplate1}" >

Dynamic double animation end - XAML

I have a progress bar that I have styled to look like the indeterminate windows ui progress bar, with the 5 ellipses going from side to side,
the animation is based inside of a canvas, the problem is my application is resolution and size independent, thus the canvas's width property is dynamic, I want to make the animation's end property (Canvas.Left) to dynamically change to the width of the canvas minus the with of the ellipse. I have tried to bind it somehow (I am still a beginner at binding) so I always get a runtime error...
Can someone please help?
Canvas:
<Canvas Name="canvas" Height="9" HorizontalAlignment="Stretch" VerticalAlignment="Center" Width="{TemplateBinding Width}">
<Ellipse Name="ellipse" Style="{DynamicResource ProgressBarEllipse}" Width="9" Fill="{TemplateBinding Foreground}" Canvas.Left="0" Canvas.Top="0" />
<Ellipse Name="ellipse1" Style="{DynamicResource ProgressBarEllipse}" Width="9" Fill="{TemplateBinding Foreground}" Canvas.Left="0" Canvas.Top="0" />
<Ellipse Name="ellipse2" Style="{DynamicResource ProgressBarEllipse}" Width="9" Fill="{TemplateBinding Foreground}" Canvas.Left="0" Canvas.Top="0" />
<Ellipse Name="ellipse3" Style="{DynamicResource ProgressBarEllipse}" Width="9" Fill="{TemplateBinding Foreground}" Canvas.Left="0" Canvas.Top="0" />
<Ellipse Name="ellipse4" Style="{DynamicResource ProgressBarEllipse}" Width="9" Fill="{TemplateBinding Foreground}" Canvas.Left="0" Canvas.Top="0" />
</Canvas>
And The Story Board:
<Storyboard RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="ellipse">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1260" KeySpline="0,1,1,0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="ellipse1">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1260" KeySpline="0,0.8,1,0.2" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="ellipse2">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1260" KeySpline="0,0.6,1,0.4" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="ellipse3">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1260" KeySpline="0,0.4,1,0.6" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="ellipse4">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1260" KeySpline="0,0.2,1,0.8" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ellipse">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ellipse1">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ellipse3">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ellipse2">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ellipse4">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
I want to change the storyboard values that are 1260 to the value of the canvas width minus the width of the ellipse

wpf storyboard for Chronometer

i have a textblock that displays second from 60 to 1 and it's foreground animate from green to red:
my xaml is like bellow and work fine:
<TextBlock x:Name="timer_check_version" Text="60" HorizontalAlignment="Center" FontSize="18">
<TextBlock.Foreground>
<SolidColorBrush x:Name="tbBrush" Color="#1e7145"/>
</TextBlock.Foreground>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ChronometerStoryboard}"/>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
and my ChronometerStoryboard is:
<Storyboard x:Key="ChronometerStoryboard">
<ColorAnimation To="#b91d47" From="#1e7145"
Duration="0:0:59"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"/>
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Text)">
<DiscreteStringKeyFrame KeyTime="0:0:1" Value="59"/>
<DiscreteStringKeyFrame KeyTime="0:0:2" Value="58"/>
<DiscreteStringKeyFrame KeyTime="0:0:3" Value="57"/>
<DiscreteStringKeyFrame KeyTime="0:0:4" Value="56"/>
<DiscreteStringKeyFrame KeyTime="0:0:5" Value="55"/>
<DiscreteStringKeyFrame KeyTime="0:0:6" Value="54"/>
<DiscreteStringKeyFrame KeyTime="0:0:7" Value="53"/>
<DiscreteStringKeyFrame KeyTime="0:0:8" Value="52"/>
<DiscreteStringKeyFrame KeyTime="0:0:9" Value="51"/>
<DiscreteStringKeyFrame KeyTime="0:0:10" Value="50"/>
......
......
......
......
<DiscreteStringKeyFrame KeyTime="0:0:51" Value="09"/>
<DiscreteStringKeyFrame KeyTime="0:0:52" Value="08"/>
<DiscreteStringKeyFrame KeyTime="0:0:53" Value="07"/>
<DiscreteStringKeyFrame KeyTime="0:0:54" Value="06"/>
<DiscreteStringKeyFrame KeyTime="0:0:55" Value="05"/>
<DiscreteStringKeyFrame KeyTime="0:0:56" Value="04"/>
<DiscreteStringKeyFrame KeyTime="0:0:57" Value="03"/>
<DiscreteStringKeyFrame KeyTime="0:0:58" Value="02"/>
<DiscreteStringKeyFrame KeyTime="0:0:59" Value="01"/>
</StringAnimationUsingKeyFrames>
</Storyboard>
the goal of above sample is to display a message to users for 60 seconds with TextBlock that counting down from 60 to 1,after 60 seconds the message and timer should be invisible and after some times according to background Threads the display of message and timer(TextBlock that counting down from 60 to 1) should be repeat,this may repeat for some times, all things work fine for first,but first the timer comes to 1,my message and timer collapsed for some minute(according to background threads) and when background threads completed i want to repeat the display of message and timer for 60 second again,but my problem is the timer value equals to 1 and timer Foreground equals to Red and no animated.
Apply AutoReverse and RepeatBeahvior attributes.
AutoReverse will make your storyboard goes exact reverse making your text color changing from Red to Green, and RepeatBehavior will make this to and fro color change continuing forever.
You can choose various RepeatBehavior settings according to your need.
<Storyboard x:Key="ChronometerStoryboard" AutoReverse="True" RepeatBehavior="Forever">
In reply to your comment :
"the visible and invisible of textblock may repeate forever and to time of invisible is random and after each visible it must start from 59 to 1 and it's foreground must start from green to red"
Use a Behavior called ControlStoryBoardAction which is present in Blend. And use it to play your storyboard.
Complete sample code might look like :
<UserControl
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:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="S32494473W.Chronometer"
x:Name="UserControl"
d:DesignWidth="632" d:DesignHeight="392">
<UserControl.Resources>
<Storyboard x:Key="ChronometerStoryboard">
<ColorAnimation To="#b91d47" From="#1e7145"
Duration="0:0:10"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="timer_check_version"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Visibility)" Storyboard.TargetName="timer_check_version">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Text)" Storyboard.TargetName="timer_check_version">
<DiscreteStringKeyFrame KeyTime="0:0:1" Value="10"/>
<DiscreteStringKeyFrame KeyTime="0:0:2" Value="9"/>
<DiscreteStringKeyFrame KeyTime="0:0:3" Value="8"/>
<DiscreteStringKeyFrame KeyTime="0:0:4" Value="7"/>
<DiscreteStringKeyFrame KeyTime="0:0:5" Value="6"/>
<DiscreteStringKeyFrame KeyTime="0:0:6" Value="5"/>
<DiscreteStringKeyFrame KeyTime="0:0:7" Value="4"/>
<DiscreteStringKeyFrame KeyTime="0:0:8" Value="3"/>
<DiscreteStringKeyFrame KeyTime="0:0:9" Value="2"/>
<DiscreteStringKeyFrame KeyTime="0:0:10" Value="1"/>
</StringAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Visibility)" Storyboard.TargetName="timer_check_version">
<DiscreteObjectKeyFrame KeyTime="0:0:10" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Button Content="Chronometer" Height="32" Margin="272,8,272,0" VerticalAlignment="Top" Click="Button_Click">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ControlStoryboardAction Storyboard="{StaticResource ChronometerStoryboard}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<TextBlock x:Name="timer_check_version" Width="100" Background="AliceBlue" Text="10" Visibility="Hidden" HorizontalAlignment="Center" FontSize="18" VerticalAlignment="Center">
<TextBlock.Foreground>
<SolidColorBrush x:Name="tbBrush" Color="#1e7145"/>
</TextBlock.Foreground>
</TextBlock>
</Grid>
</UserControl>
i change my trigger to :
<Trigger Property="IsEnabled" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ChronometerStoryboard}" Name="st1"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="st1"/>
</Trigger.ExitActions>
</Trigger>
and bind TextBlock.IsEnabled to it's Parent.Visibility and solved my problem.

BAML Error When Animating

I have the following code in a WPF 4 project, linked to an imagebox. I have four other similar instances of it that work perfectly. Why is this one throwing that vague "BAML" error we all hate (it points to the animations)? FYI, I'm using VB.net in code behind.
<Image Height="121" HorizontalAlignment="Left" Margin="139,83,0,0" Name="Spinefish" Stretch="Fill" VerticalAlignment="Top" Width="323" Source="/VBP-WORD4WORD;component/Images/IMG-SPINEFISH1.png">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" />
<TranslateTransform X="0" />
</TransformGroup>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Duration="0:0:60" RepeatBehavior="Forever" Storyboard.TargetProperty="RenderTransform.Children[1].X">
<LinearDoubleKeyFrame KeyTime="0:0:0" Value="-1000" />
<LinearDoubleKeyFrame KeyTime="0:0:25" Value="-1000" />
<LinearDoubleKeyFrame KeyTime="0:0:30" Value="1000" />
<LinearDoubleKeyFrame KeyTime="0:0:55" Value="1000" />
<LinearDoubleKeyFrame KeyTime="0:0:60" Value="-1000" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="0:0:60" RepeatBehavior="Forever" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX">
<LinearDoubleKeyFrame KeyTime="0:0:29.9" Value="1" />
<LinearDoubleKeyFrame KeyTime="0:0:30" Value="-1" />
<LinearDoubleKeyFrame KeyTime="0:0:59.9" Value="-1" />
<LinearDoubleKeyFrame KeyTime="0:0:60" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
KeyTime="0:0:60" and Duration="0:0:60" do not exist, the seconds range is from 0 to 59 only, change those to 0:1:0.

WPF Button Animation

I have a control template for a button that looks like this:
<ControlTemplate x:Key="CopyButton" TargetType="{x:Type Button}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text=">>>>"/>
</ControlTemplate>
How could I go about animating this so that when the mouse is hovering over the button the > arrows "move". I mean so that the text is something like "> ", ">> ", ">>> ", ">>>>", " >>>", " >>", " >" in a repeat.
You can use a string animation. The result is however not the most professional looking in my opinion.
<Button
Name="myAnimatedButton"
Width="200"
Content=">">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames
Storyboard.TargetName="myAnimatedButton"
Storyboard.TargetProperty="(Button.Content)"
AutoReverse="True">
<DiscreteStringKeyFrame Value=">" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value=">>" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value=">>>" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value=">>>>" KeyTime="0:0:3" />
<DiscreteStringKeyFrame Value=" >>>" KeyTime="0:0:4" />
<DiscreteStringKeyFrame Value=" >>" KeyTime="0:0:5" />
<DiscreteStringKeyFrame Value=" >" KeyTime="0:0:6" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Resources