Windows 8 - Animating custom property in code-behind
c#, windows-8, wpf
Solution
OK,
I've found the workaround for what is obviously a bug within the framework (although I'm sure some MS employee will post response and say it's a feature/it-is-by-design). Several things need to be done:
- Add default/parameter-less constructor
- Change base class of FunkyShape to UserControl.
- Open up XAML view of the Page class where you want to add shapes
- Add one instance of FunkyShape as a child within the Canvas XAML (<tm:FunkyShape /> for example). IT WON'T WORK WITHOUT THIS.
- Make an instance of FunkyShape in code-behind, add it to canvas, start animation and enjoy seeing it works
- Switch to less buggy technology.
Problem
Basically, I want to make bunch of Shapes and make them animated. So I came up with following custom class: ``` public class FunkyShape : DependencyObject { public double Animator { get { return (double)GetValue(AnimatorProperty); } set { SetValue(AnimatorProperty, value); } } public static readonly DependencyProperty AnimatorProperty = DependencyProperty.Register("Animator", typeof(double), typeof(FunkyShape), new PropertyMetadata(0, new PropertyChangedCallback(Animator_Changed))); private static void Animator_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { double delta = (double)e.NewValue - (double)e.OldValue; ((FunkyShape)d).ProcessDelta((double)e.NewValue, delta); } private void ProcessDelta(double val, double delta) { Holder.Width = val; Holder.Height = val; // Keep shape centered HolderPosition.X = delta / 2; HolderPosition.Y = delta / 2; } private Shape Holder; public TranslateTransform HolderPosition { get { return (TranslateTransform)Holder.RenderTransform; } } public FunkyShape(Canvas playground, Shape shapeToInit) { Holder = shapeToInit; Holder.Width = 10; Holder.Height = 10; Holder.Fill = new SolidColorBrush(Colors.Blue); Holder.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center; Holder.RenderTransform = new TranslateTransform() { X = 500, Y = 500 }; Holder.RenderTransformOrigin = new Point(0.5, 0.5); // init done playground.Children.Add(Holder); Animate(); } public void Animate() { DoubleAnimation g1 = GrowAnimation(); Storyboard sb = new Storyboard(); Storyboard.SetTarget(g1, this); // CAN'T FIND ANIMATOR PROPERTY Storyboard.SetTargetProperty(g1, "Animator"); sb.Children.Add(g1); sb.Begin(); // THROWS EXCEPTION } private static DoubleAnimation GrowAnimation() { DoubleAnimation growAnimation = new DoubleAnimation(); growAnimation.Duration = TimeSpan.FromMilliseconds(3000); growAnimation.From = 0; growAnimation.To = 100; growAnimation.AutoReverse = true; growAnimation.EnableDependentAnimation = true; growAnimation.RepeatBehavior = new RepeatBehavior(5); return growAnimation; } } ``` However, when I try making an instance of the class and adding it to the canvas, I get Exception - Storyboard.Being() throws it and tells me that it can't find Animator property. So - what am I doing wrong? EDIT: After 3 code changes - it is still not working; I get "Cannot resolve TargetProperty Animator on specified object" error. So if somebody knows the answer - please help out by modifying the code. Thanks! EDIT: OK, after 24 hours of banging head against the wall there is some progress - if I add shape through XAML it animates, but if I add it through code behind (Canvas.Children.Add), it doesn't work. Let me see if I can figure out why.