2010-05-15 4 views
13

У меня есть WPF-холст, на котором я динамически создаю объекты из кода. Эти объекты преобразуются путем установки свойства RenderTransform, и анимация должна быть применена к одному из этих преобразований. В настоящее время я не могу получить свойства какого-либо преобразования для анимации (хотя исключение не возникает, и анимация, как представляется, запускается - завершенное событие увеличивается).WPF: анимация TranslateTransform от кода

Кроме того, если система анимации подчеркнута, иногда событие Storyboard.Completed никогда не поднимается.

Все примеры, которые я придумал, преобразуют преобразования из XAML. MSDN documentation предполагает, что свойство x: Name преобразования должно быть настроено для его анимации, но я не нашел способ установить его из кода.

Любые идеи?

Вот полный код листинга, который воспроизводит проблему:

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

ответ

12

Кажется, что после того, как немного погуглить, я решил проблему сам. Огромное спасибо MSDN documentation и a post in MSDN forums by Antares19.

В итоге:

  • Для Freezable объекта (например, TranslateTransform), чтобы можно было выполнять с помощью раскадровки, оно должно иметь зарегистрированное имя. Это можно сделать, вызвав FrameworkElement.RegisterName (..).

  • Я добавил объект Storyboard в ResourceDictionary того же элемента Framework, на который я зарегистрировал TranslateTransform. Это может быть сделано путем вызова ResourceDictionary.Add (..)

Вот обновленный код, который теперь одушевляет красиво, и регистрирует/отменяет регистрацию добавленные ресурсы:

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

Оставьте вне раскадровки:

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

(небольшое исправление синтаксиса)

+0

хорошо и просто, вы помогли мне выделить. –

3

у меня есть решение с помощью XAML/C# Combo. В файле XAML определяют:

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

Это даст вам возможность сделать следующее в C# код:

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

Остальное как обычно. Создайте DoubleAnimation, установите его свойства, добавьте его в качестве ребенка на свою раскадровку, вызовите функцию «Начало» на панели рассказов.

Смежные вопросы