Introduction
In Silverlight, there is no ThicknessAnimation
as we can use in WPF. So like me, lots of developers would like to be able to animate the Margin
, the Padding
, or the BorderThickness
of the Border
.
Good news! I have a clean solution based on the Wrapper pattern.
How does it work?
Everything is done with the ThicknessWrapper
class:
PropertyName
is the name of the property to animate.
Side
is the side to animate; you can specify multiple values since Side
is a flag enumeration.
Target
is the target object to animate.
Value
is the size of the side of the Thickness
to animate.
The code is not very complicated; every time one of these properties change, I update the margin of the Target
.
private void UpdateMargin()
{
if(Target != null)
{
var thicknessProperty = Target.GetType().GetProperty(PropertyName);
var currentThickness = (Thickness)thicknessProperty.GetValue(Target, null);
var nextThickness = new Thickness(
CalculateThickness(Side.Left, currentThickness.Left),
CalculateThickness(Side.Top, currentThickness.Top),
CalculateThickness(Side.Right, currentThickness.Right),
CalculateThickness(Side.Bottom, currentThickness.Bottom)
);
thicknessProperty.SetValue(Target, nextThickness, null);
}
}
private double CalculateThickness(ThicknessAnimation.Side sideToCalculate,
double currentValue)
{
return (Side & sideToCalculate) == sideToCalculate ? Value : currentValue;
}
Now you just have to use the wrapper in your XAML code, and animate it. As an example, I play an animation on the BorderThickness
and on the Margin
of my border.
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Storyboard x:Key="animation">
<DoubleAnimation Storyboard.TargetName="rectTopMargin"
Storyboard.TargetProperty="Value" From="0"
To="100" Duration="00:00:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="rectStrokeThickness"
Storyboard.TargetProperty="Value" From="0"
To="20" Duration="00:00:1"></DoubleAnimation>
</Storyboard>
</Grid.Resources>
<local:ThicknessWrapper x:Name="rectTopMargin"
Target="{Binding ElementName=rect}" Side="Top"
PropertyName="Margin"></local:ThicknessWrapper>
<local:ThicknessWrapper x:Name="rectStrokeThickness"
Target="{Binding ElementName=rect}" Side="Left, Right"
PropertyName="BorderThickness"></local:ThicknessWrapper>
<StackPanel>
<Button Content="Click to animate" Click="Button_Click"></Button>
<Border x:Name="rect" HorizontalAlignment="Left"
BorderBrush="Black" VerticalAlignment="Top"
Background="Green" Height="50" Width="50"></Border>
</StackPanel>
</Grid>
Conclusion
I have not found an easier solution! :)