As part of a project I am working on, I wanted to be able to reuse a storyboard object to animate several controls the same way. At the end of the animation (the animation complete event) I needed to perform a final modification to the object. The problem with the animation object is that you can’t get back a reference to the object you animated. You can define which object to animate in two ways. In the XAML tags, you set the name of the object (Storyboard.TargetName) on the animation object attributes. In the code behind, you use the Storyboard.SetTargetName([animation object],[string]) or Storyboard.SetTarget(([animation object],[target object]). When using the SetTarget you pass the object itself.
Unfortunately, there isn’t a getTarget method on the storyboard object in the codebehind, at least not as of Beta 2. So if you reuse a storyboard and animation on multiple objects, and need to do something to that target object at the end of the animation (the completion event), how do you get at that target object? The answer is to retrieve the target name, which is available, and use it to then go get the object from the page or user control, using this.FindName([string]).
The code below shows a custom user control that reuses a storyboard and animation to impact two controls, and modify them at the animation complete event. Clicking Button1 will cause the button’s opacity to change via the animation. Clicking Button2 will do the same thing, using the same animation. Notice the complete event which affects each button individually.
<UserControl x:Class="MyNamespace.StoryboardTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Button x:Name="Button1"
Content="Button1"
Click="Button1_Click"/>
<Button x:Name="Button2"
Content="Button2"
Click="Button2_Click"/>
</StackPanel>
<Grid.Resources>
<Storyboard x:Name="Storyboard1"
Completed="Storyboard1_Completed" >
<DoubleAnimation x:Name="Animation1"
Duration="0:0:1"
Storyboard.TargetProperty="Opacity" />
</Storyboard>
</Grid.Resources>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace MyNamespace
{
public partial class StoryboardTest : UserControl
{
public StoryboardTest()
{
InitializeComponent();
}
private void Storyboard1_Completed(object sender, EventArgs e)
{
//get the name of the control that was just animated
string name = Storyboard.GetTargetName(Animation1);
//go get the button - this code assumes a button was animated
Button btnTarget = (Button)this.FindName(name);
//did the button become near invisible
//check is here just to show the animation completed
if (btnTarget.Opacity < 0.3)
{
//change the text on the button
btnTarget.Content = "Near Invisible";
}
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
//XAML code already defines the target property as Opacity
//This shows that mix of XAML and code behind works
Storyboard.SetTargetName(Animation1, Button1.Name);
Animation1.From = 1d;
Animation1.To = .2d;
Storyboard1.Begin();
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
Storyboard.SetTargetName(Animation1, Button2.Name);
Animation1.From = 1d;
Animation1.To = 0.2d;
Storyboard1.Begin();
}
}
}