in src/Microsoft.Xaml.Behaviors/Core/ChangePropertyAction.cs [194:248]
private void AnimatePropertyChange(PropertyInfo propertyInfo, object fromValue, object newValue)
{
Storyboard sb = new Storyboard();
Timeline timeline;
if (typeof(double).IsAssignableFrom(propertyInfo.PropertyType))
{
timeline = this.CreateDoubleAnimation((double)fromValue, (double)newValue);
}
else if (typeof(Color).IsAssignableFrom(propertyInfo.PropertyType))
{
timeline = this.CreateColorAnimation((Color)fromValue, (Color)newValue);
}
else if (typeof(Point).IsAssignableFrom(propertyInfo.PropertyType))
{
timeline = this.CreatePointAnimation((Point)fromValue, (Point)newValue);
}
else
{
timeline = this.CreateKeyFrameAnimation(fromValue, newValue);
}
timeline.Duration = this.Duration;
sb.Children.Add(timeline);
if (this.TargetObject == null &&
this.TargetName != null &&
this.Target is Freezable)
{
// Workaround Dev10 bug 542374, Storyboard.Target property does not work properly
// when the target of the animation is a freezable.
Storyboard.SetTargetName(sb, this.TargetName);
}
else
{
Storyboard.SetTarget(sb, (DependencyObject)this.Target);
}
Storyboard.SetTargetProperty(sb, new PropertyPath(propertyInfo.Name));
sb.Completed += (o, e) =>
{
propertyInfo.SetValue(this.Target, newValue, new object[0]);
};
sb.FillBehavior = FillBehavior.Stop;
// Give the storyboard the neccesary context to resolve target names
FrameworkElement containingObject = this.AssociatedObject as FrameworkElement;
if (containingObject != null)
{
sb.Begin(containingObject);
}
else
{
sb.Begin();
}
}