Animating margins in Silverlight
So I ran into a problem the other day where I needed to animate a margin of a control, but Silverlight doesn't allow for animating Thickness objects (WPF does). The solution I came up with is very simple and can be used to animate the Margin, Padding, or BorderThickness of any control. Since Silverlight doesn't support custom animations, we'll have to work with this hack for now.
1: using System;
2: using System.Net;
3: using System.Windows;
4: using System.Windows.Controls;
5: using System.Windows.Documents;
6: using System.Windows.Ink;
7: using System.Windows.Input;
8: using System.Windows.Media;
9: using System.Windows.Media.Animation;
10: using System.Windows.Shapes;
11:
12: namespace SLApp1
13: {
14: public class ThicknessAnimation
15: {
16: // The time along the animation from 0-1
17: public static DependencyProperty TimeProperty = DependencyProperty.RegisterAttached("Time", typeof(double), typeof(DoubleAnimation), new PropertyMetadata(OnTimeChanged));
18: // The object being animated
19: public static DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("Target", typeof(DependencyObject), typeof(ThicknessAnimation), null);
20: // The thickness we're animating to
21: public static DependencyProperty FromProperty = DependencyProperty.RegisterAttached("From", typeof(Thickness), typeof(DependencyObject), null);
22: // The tickness we're animating from
23: public static DependencyProperty ToProperty = DependencyProperty.RegisterAttached("To", typeof(Thickness), typeof(DependencyObject), null);
24: // The target property to animate to. Should have a property type of Thickness
25: public static DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached("TargetProperty", typeof(DependencyProperty), typeof(DependencyObject), null);
26:
27: /// <summary>
28: /// Creates a Timeline used to animate the thickness of an object
29: /// </summary>
30: /// <param name="target">The object to animate</param>
31: /// <param name="targetProperty">The property on the object to animate</param>
32: /// <param name="duration">The length of the animation</param>
33: /// <param name="from">The begining thickness</param>
34: /// <param name="to">The final thickness</param>
35: /// <returns>A timeline object that can be added to a storyboard</returns>
36: public static Timeline Create(DependencyObject target, DependencyProperty targetProperty, Duration duration, Thickness from, Thickness to)
37: {
38: DoubleAnimation timeAnimation = new DoubleAnimation() { From = 0, To = 1, Duration = duration };
39: timeAnimation.SetValue(TargetProperty, target);
40: timeAnimation.SetValue(TargetPropertyProperty, targetProperty);
41: timeAnimation.SetValue(FromProperty, from);
42: timeAnimation.SetValue(ToProperty, to);
43: Storyboard.SetTargetProperty(timeAnimation, new PropertyPath("(ThicknessAnimation.Time)"));
44: Storyboard.SetTarget(timeAnimation, timeAnimation);
45: return timeAnimation;
46: }
47:
48: /// <summary>
49: /// Silverlight's animation system is animating time from 0 to 1. When time changes we update the thickness to be time
50: /// percent between from and to
51: /// </summary>
52: private static void OnTimeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
53: {
54: DoubleAnimation animation = (DoubleAnimation)sender;
55: double time = GetTime(animation);
56: Thickness from = (Thickness)sender.GetValue(FromProperty);
57: Thickness to = (Thickness)sender.GetValue(ToProperty);
58: DependencyProperty targetProperty = (DependencyProperty)sender.GetValue(TargetPropertyProperty);
59: DependencyObject target = (DependencyObject)sender.GetValue(TargetProperty);
60: target.SetValue(targetProperty, new Thickness((to.Left - from.Left) * time + from.Left,
61: (to.Top - from.Top) * time + from.Top,
62: (to.Right - from.Right) * time + from.Right,
63: (to.Bottom - from.Bottom) * time + from.Bottom));
64:
65: }
66:
67: public static double GetTime(DoubleAnimation animation)
68: {
69: return (double)animation.GetValue(TimeProperty);
70: }
71:
72: public static void SetTime(DoubleAnimation animation, double value)
73: {
74: animation.SetValue(TimeProperty, value);
75: }
76: }
77: }
To use this, simply call ThicknessAnimation.Create with the necessary parameters, add the timeline to a storyboard, and call storyboard.Begin()