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

  1. Lee says:

    Hi,Ben

    How can i use the ThicknessAnimation in XAML tag? Thanks!

  2. Erwin says:

    Can you post a example. I can't figure it out. The DependencyObject and DependencyProperty cause trouble.

  3. Judah Gabriel Himango says:

    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="http://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.

  4. Nicolas Noben says:

    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.

  5. Bruno Altinet says:

    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=84

    Thanks, hope this helps to some1!