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()