2010-05-15 17 views
13

Tengo un lienzo WPF en el que estoy creando dinámicamente objetos a partir del código. Estos objetos se están transformando mediante la configuración de la propiedad RenderTransform, y una animación debe aplicarse a una de esas transformaciones. Actualmente, no puedo obtener propiedades de cualquier transformación para animar (aunque no se genera ninguna excepción y parece que la animación se ejecuta; se genera el evento completo).WPF: Animando TranslateTransform desde el código

Además, si el sistema de animación se hace hincapié, a veces, el evento se Storyboard.Completed nunca se levantó.

Todos los ejemplos que han llegado al otro lado de animar las transformaciones de XAML. MSDN documentation sugiere que la propiedad x: Name de una transformación se debe establecer para que sea animable, pero no he encontrado una manera efectiva de configurarla desde el código.

¿Alguna idea?

Aquí está el listado de código completo que reproduce el problema:

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()); 
     } 
    } 
} 

Respuesta

12

Parece que después de un poco de google me resolvió el problema mismo. Muchas gracias a MSDN documentation y a post in MSDN forums by Antares19.

En resumen:

  • Para un objeto puede congelar (como TranslateTransform) ser objeto de orientación por un guión gráfico, que debe tener un nombre registrado. Esto se puede hacer llamando a FrameworkElement.RegisterName (..).

  • I añade el objeto Storyboard a la ResourceDictionary del mismo elemento marco a la que registró la TranslateTransform. Esto se puede hacer llamando ResourceDictionary.Add (..)

Aquí está el código actualizado, que ahora anima muy bien, y los registros/anula el registro recursos añadidos:

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

dejar de lado el guión gráfico:

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); 

(pequeño arreglo de sintaxis)

+0

bueno y simple, me has ayudado a asignar. –

3

tengo una solución usando XAML/C# Combo. En su archivo XAML definen:

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

Esto le dará la capacidad de hacer lo siguiente en el código C#:

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

El resto es lo de siempre. Cree una doble animación, establezca sus propiedades, agréguela como un niño a su Guión gráfico, llame a la función Comenzar en el guión gráfico.

Cuestiones relacionadas