Reference the animated Element in the Animation’s Completed event
[updated 7/12/09 to Silverlight 3 RTW]
I had a need to create FrameworkElement(s) dynamically, animate them, and then get rid of them. I was surprised to find that while you have the (say) DoubleAnimation as one of the parameters in the Animation’s Completed handler, there’s no way to find out what FrameworkElement that Animation just animated – I want to remove that element from the visual tree.
My first idea was to extend the abstract Animation class and add a property so I could fill that property at Timeline creation and then use it in the Completed handler to remove the element. Even though that’s not the best strategy (read on), in Silverlight the various Timeline classes are sealed (not so in WPF). So, if you haven’t already guessed, Attached Properties to the rescue.
I created a static class to add an Attached Property of type FrameworkElement as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace TimelineExtensionDemo.TimelineExtensions { public static class TimelineExtension { public static readonly DependencyProperty RelatedElementProperty = DependencyProperty.RegisterAttached( "RelatedElement", typeof(FrameworkElement), typeof(TimelineExtension), null); public static void SetRelatedElement( Timeline timeline, FrameworkElement value ) { timeline.SetValue(RelatedElementProperty, value); ; } public static FrameworkElement GetRelatedElement(Timeline timeline) { return (FrameworkElement)timeline.GetValue(RelatedElementProperty); } } } |
With this in place I could now save a reference to the FrameworkElement we are about to Animate so we can operate on it after the Animation is complete. Here’s the setup, Note line #12 where we save a reference to the FrameworkElement on which one of its properties will be animated:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private void AddAnother() { TextBlock textBlock = new TextBlock(); textBlock.Text = DateTime.Now.ToString(); LayoutRoot.Children.Add(textBlock); numKids.Text = "LayoutRoot.Children= " + LayoutRoot.Children.Count.ToString(); DoubleAnimation da = new DoubleAnimation(); da.From = LayoutRoot.ActualWidth + 250; da.To = -250; da.Duration = new Duration(TimeSpan.FromSeconds(10)); TimelineExtension.SetRelatedElement(da, textBlock); da.Completed += doubleAnimation_Completed; Storyboard storyboard = new Storyboard(); Storyboard.SetTarget(da, textBlock); Storyboard.SetTargetProperty(da, new PropertyPath(Canvas.LeftProperty)); storyboard.Children.Add(da); storyboard.Begin(); } |
And here’s the Animation’s Complete event handler where we easily remove the element from the container:
1 2 3 4 5 6 | private void doubleAnimation_Completed(object sender, EventArgs e) { DoubleAnimation da = (DoubleAnimation)sender; LayoutRoot.Children.Remove(TimelineExtension.GetRelatedElement(da)); numKids.Text = "LayoutRoot.Children= " + LayoutRoot.Children.Count.ToString(); } |
To test this out I created a Demo app that scrolls text blurbs across the screen. As each TextBlock goes off screen, its Animation completes and the Completed handler Removes it from the visual tree.
Here’s a quick demo that displays the number of Children of the LayoutRoot as new textBlocks are added and removed (in the completed handler) and source (Note: Silverlight 3) is here. – Cheers!
Your browser does not support iframes.
The best information i have found exactly here. Keep going Thank you