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

Comments

  • Anonymous
    May 27, 2010
    Hi,BenHow can i use the ThicknessAnimation in XAML tag? Thanks!
  • Anonymous
    September 24, 2010
    Can you post a example. I can't figure it out. The DependencyObject and DependencyProperty cause trouble.
  • Anonymous
    November 27, 2010
    Thanks for this great example of a ThicknessAnimation in Silverlight.I used this code (with a link back to this post) in my CodeProject article: <a href="www.codeproject.com/.../pandorasilverlight.aspx">Building a Pandora clone in Silverlight 4</a>. I used the ThicknessAnimation to animate song tiles into position.Great stuff. Thanks again.
  • Anonymous
    November 27, 2010
    *Link for that article: www.codeproject.com/.../pandorasilverlight.aspx
  • Anonymous
    December 08, 2010
    Thank you so much for this. It's fantastic and it works beautifully... I'd only recommend one thing, put a massive link to that article linked in the comments that shows how to use it with a concrete example. It took me a long time to get it to work and the example was the key.Thanks again.
  • Anonymous
    January 24, 2011
    Hey, although i didn't need a thickness animation, this is the example that led me to the right route, for my grid animation. The only difference being, mine is used from xaml and i think you could refactor it also for thickness. The example is in following post:http://www.run80.net/?p=84Thanks, hope this helps to some1!
  • Anonymous
    May 26, 2011
    I have refactored this code to be able to use set it in XAML www.microdivision.com/.../animating-thickness-and-margin-properties-in-silverlight