2010-05-15 3 views
13

J'ai un canevas WPF sur lequel je crée dynamiquement des objets à partir du code. Ces objets sont en cours de transformation en définissant la propriété RenderTransform et une animation doit être appliquée à l'une de ces transformations. Actuellement, je ne peux pas obtenir les propriétés d'une transformation à animer (bien qu'aucune exception ne soit levée et que l'animation semble s'exécuter - l'événement terminé est levé).WPF: Animation de TranslateTransform à partir du code

En outre, si le système d'animation est sollicité, il arrive que l'événement Storyboard.Completed ne soit jamais déclenché.

Tous les exemples que j'ai rencontrés animent les transformations de XAML. MSDN documentation suggère que la propriété x: Name d'une transformation doit être définie pour qu'elle soit animable, mais je n'ai pas trouvé de moyen de le définir à partir du code.

Des idées?

est ici la liste complète des codes qui reproduit le problème:

using System; 
using System.Diagnostics; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 

namespace AnimationCompletedTest { 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window { 

     Canvas panel; 
     public MainWindow() { 
      InitializeComponent(); 
      MouseDown += DoDynamicAnimation; 

      Content = panel = new Canvas(); 
     } 

     void DoDynamicAnimation(object sender, MouseButtonEventArgs args) { 

      for (int i = 0; i < 12; ++i) { 
       var e = new Ellipse { 
        Width = 16, 
        Height = 16, 
        Fill = SystemColors.HighlightBrush 
       }; 
       Canvas.SetLeft(e, Mouse.GetPosition(this).X); 
       Canvas.SetTop(e, Mouse.GetPosition(this).Y); 

       var tg = new TransformGroup(); 
       var translation = new TranslateTransform(30, 0); 
       tg.Children.Add(translation); 
       tg.Children.Add(new RotateTransform(i * 30)); 
       e.RenderTransform = tg; 

       panel.Children.Add(e); 

       var s = new Storyboard(); 
       Storyboard.SetTarget(s, translation); 
       Storyboard.SetTargetProperty(s, new PropertyPath(TranslateTransform.XProperty)); 

       s.Children.Add(
        new DoubleAnimation(3, 100, new Duration(new TimeSpan(0, 0, 0, 1, 0))) { 
         EasingFunction = new PowerEase {EasingMode = EasingMode.EaseOut} 
        }); 

       s.Completed += 
        (sndr, evtArgs) => { 
         Debug.WriteLine("Animation {0} completed {1}", s.GetHashCode(), Stopwatch.GetTimestamp()); 
         panel.Children.Remove(e); 
        }; 

       Debug.WriteLine("Animation {0} started {1}", s.GetHashCode(), Stopwatch.GetTimestamp()); 

       s.Begin(); 
      } 
     } 

     [STAThread] 
     public static void Main() { 
      var app = new Application(); 
      app.Run(new MainWindow()); 
     } 
    } 
} 

Répondre

12

semble que, après un peu de recherche sur Google, je me résolu le problème. Un grand merci à MSDN documentation et a post in MSDN forums by Antares19.

En résumé:

  • Pour un objet Freezable (comme TranslateTransform) être par un Storyboard ciblable, il doit avoir un nom enregistré. Cela peut être fait en appelant FrameworkElement.RegisterName (..).

  • J'ai ajouté l'objet Storyboard au ResourceDictionary du même élément Framework dans lequel j'ai enregistré TranslateTransform. Cela peut être fait en appelant ResourceDictionary.Add (..)

Voici le code mis à jour, qui anime maintenant bien, et les registres/désinscrit les ressources ajoutées:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 

namespace AnimationCompletedTest { 

    public partial class MainWindow : Window { 

     Canvas panel; 
     public MainWindow() { 
      InitializeComponent(); 
      MouseDown += DoDynamicAnimation; 

      Content = panel = new Canvas(); 
     } 

     void DoDynamicAnimation(object sender, MouseButtonEventArgs args) { 
      for (int i = 0; i < 12; ++i) { 
       var e = new Ellipse { Width = 16, Height = 16, Fill = SystemColors.HighlightBrush }; 
       Canvas.SetLeft(e, Mouse.GetPosition(this).X); 
       Canvas.SetTop(e, Mouse.GetPosition(this).Y); 

       var tg = new TransformGroup(); 
       var translation = new TranslateTransform(30, 0); 
       var translationName = "myTranslation" + translation.GetHashCode(); 
       RegisterName(translationName, translation); 
       tg.Children.Add(translation); 
       tg.Children.Add(new RotateTransform(i * 30)); 
       e.RenderTransform = tg; 

       panel.Children.Add(e); 

       var anim = new DoubleAnimation(3, 100, new Duration(new TimeSpan(0, 0, 0, 1, 0))) { 
        EasingFunction = new PowerEase { EasingMode = EasingMode.EaseOut } 
       }; 

       var s = new Storyboard(); 
       Storyboard.SetTargetName(s, translationName); 
       Storyboard.SetTargetProperty(s, new PropertyPath(TranslateTransform.YProperty)); 
       var storyboardName = "s" + s.GetHashCode(); 
       Resources.Add(storyboardName, s); 

       s.Children.Add(anim); 

       s.Completed += 
        (sndr, evtArgs) => { 
         panel.Children.Remove(e); 
         Resources.Remove(storyboardName); 
         UnregisterName(translationName); 
        }; 
       s.Begin(); 
      } 
     } 

     [STAThread] 
     public static void Main() { 
      var app = new Application(); 
      app.Run(new MainWindow()); 
     } 
    } 
} 
21

Laissez le Storyboard:

var T = new TranslateTransform(40, 0); 
Duration duration = new Duration(new TimeSpan(0, 0, 0, 1, 0)); 
DoubleAnimation anim = new DoubleAnimation(30, duration); 
T.BeginAnimation(TranslateTransform.YProperty, anim); 

(petit correctif pour la syntaxe)

+0

bon et simple, vous m'avez aidé à attribuer. –

3

J'ai une solution en utilisant XAML/C# Combo. Dans votre fichier XAML définir:

<UserControl.RenderTransform> 
    <TranslateTransform x:Name="panelTrans" Y="0"></TranslateTransform> 
</UserControl.RenderTransform> 

Cela vous donnera la possibilité de faire ce qui suit dans le code C#:

 Storyboard.SetTargetName(mFlyInDA, "panelTrans"); 
     Storyboard.SetTargetProperty(mFlyInDA, new PropertyPath("Y")); 

Le reste est comme d'habitude. Créez un DoubleAnimation, définissez ses propriétés, ajoutez-le en tant qu'enfant à votre Storyboard, appelez la fonction Begin sur le storyboard.