2010-02-26 9 views
8

J'ai créé une sous-classe simple de StackPanel que je peux déplacer à l'écran en utilisant une animation TranslateTransform. Il ressemble à ceci:Pourquoi ces animations ne fonctionnent-elles pas lorsque j'utilise un storyboard?

public class MovingStackPanel : StackPanel 
{ 
    public void BeginMove(Point translatePosition) 
    { 
     RenderTransform = new TranslateTransform(); 
     Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400)); 
     DoubleAnimation x = new DoubleAnimation(translatePosition.X, d); 
     DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d); 
     /* 
     Storyboard.SetTarget(x, RenderTransform); 
     Storyboard.SetTargetProperty(x, new PropertyPath("X")); 

     Storyboard.SetTarget(y, RenderTransform); 
     Storyboard.SetTargetProperty(y, new PropertyPath("Y")); 

     Storyboard sb = new Storyboard(); 
     sb.Children.Add(x); 
     sb.Children.Add(y); 
     sb.Completed += sb_Completed; 
     sb.Begin(); 
     */ 
     RenderTransform.BeginAnimation(TranslateTransform.XProperty, x); 
     RenderTransform.BeginAnimation(TranslateTransform.YProperty, y); 
    } 

    void sb_Completed(object sender, EventArgs e) 
    { 
     Console.WriteLine("Completed."); 
    } 
} 

Et voici mon problème: Si je les propriétés X anime et Y directement, comme le code ci-dessus ne, cela fonctionne. Mais si j'utilise le code commenté ci-dessus, ce qui est vraiment la création la plus simple d'un Storyboard dans le code imaginable, rien ne se passe. L'animation tourne - au moins, l'événement Completed est levé - mais rien ne change à l'écran. De toute évidence, je fais quelque chose de mal, mais je ne peux pas voir ce que c'est. Chaque exemple de création de storyboards dans le code que j'ai vu ressemble à ceci. Il y a évidemment quelque chose à propos des animations et des story-boards que je ne connais pas encore: qu'est-ce que c'est?

+1

FYI - J'ai signalé cela comme un bug sur Microsoft Connect. https://connect.microsoft.com/VisualStudio/feedback/details/723701/storyboard-settarget-only-works-on-uielements-but-throws-no-exception –

Répondre

10

Comme il se trouve, vous ne pouvez pas utiliser la syntaxe de chemin de propriété dans ce cas, parce que les propriétés ne sont pas animés étant propriétés d'un FrameworkElement. Au moins, c'est mon interprétation de l'exception remarquable ahurissant que je reçois quand je fais le changement Anvaka suggéré:

Cannot automatically create animation clone for frozen property values on  
'System.Windows.Media.TranslateTransform' objects. Only FrameworkElement and 
FrameworkContentElement (or derived) types are supported. 

Animer ceux-ci, il semble, je dois utiliser un NameScope et utiliser SetTargetName pour nommer le TransformElement . Ensuite, tant que je passe le FrameworkElement que j'ai défini la portée du nom sur la méthode Begin, le storyboard peut trouver l'objet et les propriétés et les animer et tout fonctionne. Le résultat final ressemble à ceci:

public void BeginMove(Point translatePosition) 
{ 
    NameScope.SetNameScope(this, new NameScope()); 

    RenderTransform = new TranslateTransform(); 
    RegisterName("TranslateTransform", RenderTransform); 

    Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400)); 
    DoubleAnimation x = new DoubleAnimation(translatePosition.X, d); 
    DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d); 

    Storyboard.SetTargetName(x, "TranslateTransform"); 
    Storyboard.SetTargetProperty(x, new PropertyPath(TranslateTransform.XProperty)); 

    Storyboard.SetTargetName(y, "TranslateTransform"); 
    Storyboard.SetTargetProperty(y, new PropertyPath(TranslateTransform.YProperty)); 

    Storyboard sb = new Storyboard(); 
    sb.Children.Add(x); 
    sb.Children.Add(y); 
    sb.Completed += sb_Completed; 

    // you must pass this to the Begin method, otherwise the timeline won't be 
    // able to find the named objects it's animating because it doesn't know 
    // what name scope to look in 

    sb.Begin(this); 

} 
7

C'est la syntaxe property path. L'approche suivante fonctionne:

public void BeginMove(Point translatePosition) 
{ 
    RenderTransform = new TranslateTransform(); 
    Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400)); 
    DoubleAnimation x = new DoubleAnimation(translatePosition.X, d); 
    DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d); 

    Storyboard.SetTarget(x, this); 
    Storyboard.SetTargetProperty(x, 
       new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)")); 

    Storyboard.SetTarget(y, this); 
    Storyboard.SetTargetProperty(y, 
       new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); 

    Storyboard sb = new Storyboard(); 
    sb.Children.Add(x); 
    sb.Children.Add(y); 
    sb.Completed += sb_Completed; 
    sb.Begin(); 

    //RenderTransform.BeginAnimation(TranslateTransform.XProperty, x); 
    //RenderTransform.BeginAnimation(TranslateTransform.YProperty, y); 
}