The why: I am trying to implement an extension for Storyboard (or more generally TimelineGroup) that can be run after Storyboard.Completed to "unlock" the animated properties, and leaving them at their new value (quite a goofy workaround in itself, see Boolean Animation locks property for background).
So the extension below provides a uniform way of doing this rather than trying to keep track of each property changed & what the value was expected end up as.
public static void ReleaseAnimatedProperties(this TimelineGroup storyboard) {
foreach (Timeline anim in storyboard.Children) {
// This is null unless Storyboard.SetTarget(anim, <animatable>) has been called
Animatable animatable = (Animatable)Storyboard.GetTarget(anim);
PropertyPath path = Storyboard.GetTargetProperty(anim);
DependencyProperty dp = (DependencyProperty)path.PathParameters[0];
animatable.SetValue(dp, animatable.GetValue(dp)); // Set it to what it ended up as
animatable.ApplyAnimationClock(dp, null); // Drop the "locking" on the animated property
}
}
The what: How can I retrieve the Storyboard.Target?
Storyboard.GetTarget returns null UNLESS Storyboard.SetTarget was used. But when the target is not a UIElement (for instance when it is a ScaleTransform), SetTarget will cause the animation to fail. Instead (and not in addition) Storyboard.SetTargetName must be used. See this issue: Storyboard.SetTarget vs Storyboard.SetTargetName. So we've got a catch-22 - is there any other way to pull out the Storyboard.Target (and not just its name) from an animation?
I'm aware I can tack on a bunch of anonymous methods as the animation is built, so that I know which object I'm dealing with, but this would be so much cleaner.