Windows 8 – Animieren von benutzerdefinierten Eigenschaften in CodeBehind

Grundsätzlich möchte ich eine Menge Shapes erstellen und animieren. Also kam ich mit folgender 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; } } 

Wenn ich jedoch versuche, eine Instanz der class zu erstellen und sie der Zeichenfläche hinzuzufügen, bekomme ich Exception – Storyboard.Being () wirft sie und sagt mir, dass sie die Animator-Eigenschaft nicht finden kann.

Also, was mache ich falsch?

BEARBEITEN: Nach 3 Codeänderungen – es funktioniert immer noch nicht; Ich erhalte den Fehler “TargetProperty Animator für angegebenes Objekt kann nicht aufgetriggers werden”. Wenn also jemand die Antwort kennt, helfen Sie bitte, indem Sie den Code ändern. Vielen Dank!

BEARBEITEN: OK, nach 24 Stunden Kopfstoß gegen die Wand gibt es einige Fortschritte – wenn ich Form durch XAML hinzufüge, wird es animiert, aber wenn ich es durch Code hinterher (Canvas.Children.Add) hinzufüge, funktioniert es nicht. Lassen Sie mich sehen, ob ich herausfinden kann, warum.

OK,

Ich habe die Problemumgehung für einen offensichtlichen Fehler innerhalb des Frameworks gefunden (obwohl ich mir sicher bin, dass einige MS-Mitarbeiter eine Antwort posten und sagen, es sei eine function / ein Design, das sich nach dem Design richtet). Einige Dinge müssen getan werden:

  1. Fügen Sie einen Standardkonstruktor ohne Parameter hinzu
  2. Ändern Sie die Basisklasse von FunkyShape in UserControl.
  3. Öffnen Sie die XAML-Ansicht der Seitenklasse, in der Sie Formen hinzufügen möchten
  4. Fügen Sie eine Instanz von FunkyShape als untergeordnetes Element in der Canvas-XAML hinzu (z. B. ). Ohne es funktioniert es nicht.
  5. Erstellen Sie eine Instanz von FunkyShape in Code-Behind, fügen Sie sie zur Zeichenfläche hinzu, starten Sie die Animation und genießen Sie die functionsweise
  6. Wechseln Sie zu weniger errorshaften Technologien.

In Windows 8 können Sie keine benutzerdefinierten Eigenschaften animieren, ohne auch die Eigenschaft enabledependentanimation auf true zu setzen. Das liegt daran, dass nicht deterministische Animationen standardmäßig deaktiviert sind.

Referenz: http://msdn.microsoft.com/de-de/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx

Ja, Sie müssen diese Eigenschaft als Abhängigkeitseigenschaft definieren, nicht nur als reguläre CLR-Eigenschaft. Dies beinhaltet ziemlich viel einfachen Kesselplattencode. Siehe dazu den Blogbeitrag für ein vollständiges Beispiel:

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

OK, ich hatte auch dieses Problem, aber ich wollte keinen öffentlichen parameterlosen Konstruktor in meine class aufnehmen, also habe ich einen anderen Weg gefunden.

Grundsätzlich besteht das Problem darin, dass WinRT eine native Plattform ist und .NET-Code nicht reflektieren kann. Aus diesem Grund werden beim Erstellen von WinRT-Apps Metadaten zu den in XAML verwendeten Typen generiert (den entsprechenden Code finden Sie in obj/(Debug|Release)/XamlTypeInfo.g.cs ).

Wenn ein Typ nie in XAML verwendet wird, werden keine Metadaten zu diesem Typ generiert. Dies bedeutet (unter anderem), dass Sie die Eigenschaften des Typs nicht animieren können.

Wenn Sie eine classnbibliothek schreiben, können Sie einfach ein XAML-Ressourcenwörterbuch hinzufügen und eine Dummy-Instanz des Typs deklarieren. Dadurch werden Metadaten generiert. Voraussetzung ist jedoch, dass der Typ über einen öffentlichen parameterlosen Konstruktor verfügt, was möglicherweise nicht wünschenswert ist.

Es gibt also eine andere Lösung: Stellen Sie die Metadaten selbst bereit. Es gibt mehrere Schnittstellen, die implementiert werden müssen, und sie haben viele Mitglieder. Daher kann es ziemlich langwierig sein, sie manuell auszuführen. Zum Glück musst du nicht! Folgendes kannst du tun:

  • füge einen öffentlichen parameterlosen Konstruktor zur class hinzu (vorübergehend)
  • Erstellen Sie ein XAML- ResourceDictionary und deklarieren Sie eine Instanz der class darin (wie oben beschrieben).
  • kopiere die Datei XamlTypeInfo.g.cs in dein Projekt (ich habe sie in XamlTypeInfo.cs )
  • Ersetzen Sie den Aufruf an den Konstruktor durch throw new NotImplementedException()
  • Löschen Sie die ResourceDictionary Datei
  • Entfernen Sie den öffentlichen parameterlosen Konstruktor

Und fertig, die Animation funktioniert jetzt einwandfrei.

Der process ist immer noch recht langwierig, daher wäre es schön, ein Werkzeug zu haben, das die Arbeit für uns erledigt …


BEARBEITEN: wesentlich einfachere Lösung: [Bindable] Attribut [Bindable] auf die class an. Dadurch wird der Typ des Metadatengenerators berücksichtigt, auch wenn er nicht in XAML verwendet wird. (Ignorieren Sie die Tatsache, dass das Dokument sagt, es sei für C ++ – Typen; es funktioniert auch für C # -classn gut.)