How to count how many times storyboard animation looped? - c#

I have code like this
<Storyboard x:Key="AdvMarquee" Completed="Storyboard_Completed">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" From="-25" To="0" BeginTime="0:00:00" Duration="0:00:01" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" From="0" To="25" BeginTime="0:00:03" Duration="0:00:01" />
</Storyboard>
<Style x:Key="AnimationImageStyle" TargetType="StackPanel">
<Setter Property="Canvas.Top" Value="200" />
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource AdvMarquee}"/>
</EventTrigger>
</Style.Triggers>
</Style>
And Applied this Animation style with this code
<Canvas x:Name="Advertise" Background="{x:Null}" Margin="10,0,0,0" >
<StackPanel Style="{StaticResource AnimationImageStyle}">
<Button Click="Advertise_Click" Style="{StaticResource AdvertisementBtnStyle}">
<TextBlock Name="AdvText" Text="This is Animated Text" Padding="10, 0, 10, 0"/>
</Button>
</StackPanel>
</Canvas>
I've tried to use Completed Event on Storyboard to calculate how many times Storyboard animation executed.
Before this, I tried to add RepeatBehavior="Forever" on Storyboard but it just loop forever and didn't run completed event.
and now, when I remove RepeatBehavior="Forever", it complete it's progress, count up, but it doesn't run again.
how can I solve this problem?
still have no idea cuz I'm really new to work with xaml wpfform.
My Storyboard_Completed is just like this.
int count = 0;
private void Storyboard_Completed( object sender, EventArgs e )
{
count++;
}

Put event handler for CurrentStateInvalidated for the last animation and you will have the possibility to get current iteration:
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" From="0" To="25" BeginTime="0:00:03" Duration="0:00:01" CurrentStateInvalidated="DoubleAnimation_CurrentStateInvalidated"/>
int cnt=0;
private void DoubleAnimation_CurrentStateInvalidated(object sender, EventArgs e)
{
var ac = sender as AnimationClock;
cnt = (ac.Parent as ClockGroup).CurrentIteration;
}
Storyboard_Completed you will not need.

Related

How to add objects to Canvas after ellipse reaches middle of the Canvas?

I am animating the ellipse to move horizontally in wpf. Now I want to add few more ellipses on to the canvas when ellipse reaches certain point on canvas (let's say midpoint of the canvas). How can I achieve this?
XAML code-
<Canvas Background="AliceBlue" x:Name="canvas">
<Ellipse
Name="ellipse1"
Canvas.Left="50"
Fill="#FFFFFF00"
Height="75"
Width="100"
/>
</Canvas>
Code behind-
public partial class MainWindow : Window
{
private DoubleAnimation anim = new System.Windows.Media.Animation.DoubleAnimation(50, 400, TimeSpan.FromSeconds(10),
System.Windows.Media.Animation.FillBehavior.HoldEnd);
private AnimationClock clock;
public MainWindow()
{
InitializeComponent();
clock = anim.CreateClock();
this.ellipse1.ApplyAnimationClock(Canvas.LeftProperty, clock);
}
}
Initially I thought it was simple, I would just access Canvas.Left from code behind and when it reaches the value I want, I would add the ellipses. But I am struggling to implement this, I guess I would need some kind of watcher or event to achieve this. How should I implement it?
Create two storyboards. Each one does half the animation. When the first storyboard completes start the second storyboard and add the other ellipses.
XAML
<Window.Resources>
<Storyboard x:Key="StartingStoryboard"
Completed='Storyboard_Completed'>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="ellipse1">
<EasingDoubleKeyFrame KeyTime="0"
Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2"
Value="100" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="EndingStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="ellipse1">
<EasingDoubleKeyFrame KeyTime="0"
Value="100" />
<EasingDoubleKeyFrame KeyTime="0:0:2"
Value="200" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource StartingStoryboard}" />
</EventTrigger>
</Window.Triggers>
<Canvas Background="AliceBlue"
x:Name="canvas1">
<Ellipse Name="ellipse1"
Fill="#FFFFFF00"
Height="75"
Width="100"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
Code
private void Storyboard_Completed(object sender, EventArgs e) {
var sb = FindResource("EndingStoryboard") as Storyboard;
sb.Begin();
var orangeEllipse = new Ellipse();
orangeEllipse.Fill = new SolidColorBrush(Colors.Orange);
orangeEllipse.Width = orangeEllipse.Height = 40;
canvas1.Children.Add(orangeEllipse);
}

C# WPF pausing an animated window with storyboard

I am making a C# wpf application with Visual Studio 2012. Here is the toast like notification. It is animated to go off by 4 seconds. It I get the mouse over this I want to pause the animation.
How can I achieve that ?
<Window x:Class="Exmaple.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
Title="Notification Popup" Width="300" SizeToContent="Height"
WindowStyle="None" AllowsTransparency="True" Height="Auto" Background="Transparent">
<Grid x:Name="abc" RenderTransformOrigin="0,1" Height="Auto" Width="300" Margin="0,0,0,0" MouseEnter="Grid_MouseEnter_1" >
<!-- Notification area -->
<Border BorderThickness="1" Background="#FF2D2D30" BorderBrush="Black" CornerRadius="0" Margin="0,0,0,0">
<!--StackPanel Margin="20"-->
<TextBlock x:Name="textblocknotify" TextWrapping="Wrap" Height="Auto" Margin="5" Foreground="White">
</TextBlock>
<!--CheckBox Content="Checkable" Margin="5 5 0 5" /-->
<!--Button Content="Clickable" HorizontalAlignment="Center" /-->
<!--/StackPanel-->
</Border>
<!-- Animation -->
<Grid.Triggers >
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Completed="Storyboard_Completed_1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:4.5" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard Completed="Storyboard_Completed_1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:4.5" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.RenderTransform>
<ScaleTransform ScaleY="1" />
</Grid.RenderTransform>
</Grid>
Code behind this
public partial class Window1 : Window
{
public Window1(String s)
{
InitializeComponent();
textblocknotify.Text = s;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
var workingArea = System.Windows.SystemParameters.WorkArea;
var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom));
this.Left = corner.X - this.ActualWidth - 10;
this.Top = corner.Y - this.ActualHeight-30;
}));
//this.Close();
}
private void Storyboard_Completed_1(object sender, EventArgs e)
{
this.Close();
}
private void Grid_MouseEnter_1(object sender, MouseEventArgs e)
{
//don't know what to do
}
You can use the PauseStoryboard Class and the UIElement.MouseEnter Event to pause a running Animation. Equally, if you want the Animation to resume when the mouse is no longer over the control, then you can use the ResumeStoryboard Class and the UIElement.MouseLeave Event. Here is a simple example to demonstrate:
<Button Content="Click Me">
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Name="OpacityStoryboard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)"
From="0" To="1" RepeatBehavior="Forever" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<PauseStoryboard BeginStoryboardName="OpacityStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<ResumeStoryboard BeginStoryboardName="OpacityStoryboard" />
</EventTrigger>
</Button.Triggers>
</Button>

how declare a storyboard in xaml and run it from code

I want to increase current window height when click on button.
I use this code:
private void sendbtn_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = this.Height;
myDoubleAnimation.To = 500;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, this.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Window.HeightProperty));
myStoryboard.Begin(this);
}
but I want declare my storyboard in xaml and run it from code.
but I dont know how do this ??
You can put it in a resource dictionary and reference it from code. Alternatively, you could use an event trigger to start the Storyboard in XAML:
<UserControl.Resources>
<Storyboard x:Key="TheStoryboard">
<DoubleAnimation Storyboard.TargetProperty="Height"
To="500" Duration="0:0:0.5"
Storyboard.TargetName="X" /> <!-- no need to specify From -->
</Storyboard>
</UserControl.Resources>
To start from code:
((Storyboard)this.Resources["TheStoryboard"]).Begin(this);
To start from XAML:
<UserControl.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="TheButton">
<BeginStoryboard Storyboard="{StaticResource TheStoryboard}"/>
</EventTrigger>
</UserControl.Triggers>
Where the button is assigned the name:
<Button Name="TheButton" Content="Start" />
Declare the storyboard as resource in your Window.
Give it a key.
<Window.Resources>
<Storyboard x:Key="test">
...
</Storyboard>
</Window.Resources>
Find the resource:
Storyboard sb = this.FindResource("test") as Storyboard;
Use it:
sb.Begin();
Storyboard sb = (Storyboard)btnPause.FindResource("PauseStoryboard");
//to start
sb.Begin(btnPause, true);
//to stop
sb.Stop(btnPause);
<Button x:Name="btnPause" Width="28" Background="LightCyan" Click="btnPause_Click">
<Image Source="Images\pause.png"></Image>
<Button.Resources>
<Storyboard x:Key="PauseStoryboard">
<ColorAnimation To="Yellow" Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>
</Button.Resources>
</Button>

text highlighting animation in windows 8 apps

i want to create an animation where each word of a line changes its foreground color from black to white after some intervals.
initially all the words are set to black.
i have used this code:
DispatcherTimer text1timer = new DispatcherTimer();
text1timer.Interval = TimeSpan.FromMilliseconds(440);
text1timer.Tick += text1timer_Tick;
text1timer.Start();
void text1timer_Tick(object sender, object e)
{
text1timer.Tick -= text1timer_Tick;
txt1.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text2timer_Tick;
text1timer.Start();
}
private void text2timer_Tick(object sender, object e)
{
text1timer.Tick -= text2timer_Tick;
txt2.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text3timer_Tick;
text1timer.Start();
}
private void text3timer_Tick(object sender, object e)
{
text1timer.Tick -= text3timer_Tick;
txt3.Foreground = new SolidColorBrush(Colors.White);
text1timer.Stop();
text1timer.Tick += text4timer_Tick;
text1timer.Start();
}
and so on but i have more than 100 words and i will have to make more than 100 events of the timer.is there any other solution?
You can use StoryBoard for the desired functionality.Check the following codes.
<Page.Resources>
<Storyboard x:Name="TextForegroundSb" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Tag)" Storyboard.TargetName="textBlock">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="Red"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="Green"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4" Value="Blue"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
Here is the Textblock
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="TextBlock" FontSize="48" Tag="Red" FontWeight="Bold" Foreground="{Binding Tag, RelativeSource={RelativeSource Mode=Self}}" FontFamily="Global User Interface" />
Also you can modify the time by changing DiscreteObjectKeyFrame KeyTime property.
For playing the storyboard on a button click use this code.
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" <br/>
xmlns:Core="using:Microsoft.Xaml.Interactions.Core" <br/>
xmlns:Media="using:Microsoft.Xaml.Interactions.Media" <br/>
<Button Content="Start sb" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="915,285,0,0" Height="119" Width="276">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Media:ControlStoryboardAction Storyboard="{StaticResource TextForegroundSb}"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
Hope this helps.
Thanks..
Use storyboard! there are instructions online and on MSDN.

change color of button in wpf C# after click and after 2 minutes retain the original color

I am using this code
Hello.Background = System.Windows.Media.Brushes.Blue;
var dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(61);
TimeSpan span = new TimeSpan(0,1,0);
dispatcherTimer.Start();
dispatcherTimer.Tick += delegate
{
if (dispatcherTimer.Interval > span)
{
Hello.Background = System.Windows.Media.Brushes.Red;
dispatcherTimer.Stop();
}
};
But button keeps fade in and fade out.
i want color to be constant
C#
private void Button_Click(object sender, RoutedEventArgs e)
{
Hello.Background = System.Windows.Media.Brushes.Blue;
var dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(61);
TimeSpan span = new TimeSpan(0,1,0);
dispatcherTimer.Start();
dispatcherTimer.Tick += delegate
{
if (dispatcherTimer.Interval > span)
{
Hello.Background = System.Windows.Media.Brushes.Red;
dispatcherTimer.Stop();
}
};
}
Xaml
<Button Name="Hello" Content="Hello" Background="White" Foreground="Black " Click="Button_Click">
</Button>
You could just create a Style and use a Trigger to start a Storyboard with ColorAnimations
Example:
<Style x:Key="AnimatedButton" TargetType="Button">
<Setter Property="Background" Value="Red" />
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard Storyboard.TargetProperty="Background.Color">
<ColorAnimation To="Blue" Duration="0:0:4" />
<ColorAnimation To="Red" BeginTime="0:1:52" Duration="0:0:4" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
Just tried it now ..... however this is code behind
XAML Code:
<Button Content="Button" x:Name="MyButton" Height="23" HorizontalAlignment="Left"
Margin="94,128,0,0" VerticalAlignment="Top" Width="75"/>
Cs File
private void StartAnimation()
{
Color fromRGB= Color.FromRgb(255, 255, 255); ;
Color ToRGB= Color.FromRgb(255, 0, 0);
SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = Colors.Black;
ColorAnimation myAnimation = new ColorAnimation();
myAnimation.From = fromRGB;
myAnimation.To = ToRGB;
myAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(120000));
myAnimation.AutoReverse = true;
myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myAnimation );
MyButton.Background = myBrush;
}
you can change the color when your event is called and then call your animation.
Just to show a different approach really ... If you're using MVVM, you could bind your button color to a property on the ViewModel, and once you click on it, run your 2 minutes background/timer . Once the 2 minutes are done, it'll change the color to the other one.
Not much xaml involved, and I do like some of the other solutions here :)
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(2000); // two second
ButtonColorPropertyName= Colors.Red;
}
(Assuming you have the ButtonColorPropertyName or whatever you want to name it, in the ViewModel)
could you try to use a simple StoryBoard created in Blend and then apply to Button/style
something like this:
<Button Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="75" >
<Button.Background>
<SolidColorBrush x:Name="MySolidColorBrush" Color="Brown" />
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Red" To="Yellow" Duration="0:0:0" RepeatBehavior="1x" />
<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Yellow" To="Blue" Duration="0:0:0" RepeatBehavior="1x" BeginTime="0:0:10" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>

Categories