Windows 8 - Animating a Custom Property in Code

Basically, I want to create a bunch of shapes and make them animated. So I came up with the 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 to make an instance of the class and add it to the canvas, I get Exception-Storyboard.Being (), throws it out and tells me that it cannot find the Animator property.

So - what am I doing wrong?

EDIT: After 3 code changes - it still does not work; I get the error "Unable to resolve TargetProperty Animator on error on the specified object." Therefore, if someone knows the answer - please help by changing the code. Thanks!

EDIT: OK, after 24 hours banging my head against the wall there is some progress - if I add the form through XAML, it animates, but if I add it through the code (Canvas.Children. Add), it does not work. Let me see if I can understand why.

+7
source share
4 answers

Ok

I found a workaround for what, obviously, is a mistake within the framework (although I am sure that some MS employee will post the answer and say that this is a function / design). There are a few things to do:

  • Add default / parameter-less constructor
  • Change the base class of FunkyShape to UserControl.
  • Open the XAML view for the Page class where you want to add shapes
  • Add one instance of FunkyShape as a child of the Canvas XAML (e.g. FunkyShape />). IT DOES NOT WORK WITHOUT IT.
  • Make an instance of FunkyShape encoded, add it to the canvas, start the animation and enjoy how it works.
  • Switch to less robust technology.
+6
source

On Windows 8, you cannot animate custom properties without setting the enabledependentanimation property to true. This is because non-deterministic animations are disabled by default.

Link: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx

+3
source

Yes, you should define this property as a dependency property, and not just a regular CLR property. This includes a fairly simple boiler plate code. See Thus a blog post for a complete example:

http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx

+1
source

Well, I had this problem too, but I didn't want to include a public constructor without parameters in my class, so I found another way.

The main problem is that WinRT is a native platform and cannot reflect .NET code. Therefore, the build process for WinRT applications generates metadata about the types used in XAML (you can find the corresponding code in obj/(Debug|Release)/XamlTypeInfo.g.cs ).

If a type is never used in XAML, metadata of this type is not generated, which means (by the way) that you cannot animate properties of this type.

If you are writing a class library, you can simply turn on the XAML resource dictionary and declare a dummy type instance; this will lead to metadata generation. However, this requires the type to have an open constructor without parameters. This may be undesirable.

So, there is another solution: provide the metadata yourself. There are several interfaces to implement, and they have many members, so this can be quite tedious to do manually. Fortunately, you don’t have to! Here is what you can do:

  • add an open class without parameters to the class (temporarily)
  • create a XAML ResourceDictionary and declare an instance of the class in it (as described above)
  • copy the XamlTypeInfo.g.cs file to your project (I renamed it to XamlTypeInfo.cs )
  • replace the constructor call with throw new NotImplementedException()
  • delete the ResourceDictionary file
  • remove open constructor without parameters

And you're done, the animation now works correctly.

The process is still quite tedious, so it would be nice to have a tool to do this work for us ...


EDIT: much simpler: apply the [Bindable] attribute to the class. This makes the metadata generator type-sensitive, even if it is not used in XAML. (ignore the fact that the document talks about it for C ++ types, it works great for C # classes too)

+1
source

All Articles