У меня есть холст WPF, на котором я динамично создаю объекты из кода. Эти объекты преобразовываются путем установки свойства RenderTransform, и анимация должна быть применена одно из тех преобразований. В настоящее время я не могу добраться, свойства любого преобразовывают для анимации (хотя никакое исключение не повышено, и анимация, кажется, работает - завершенное событие генерируется).
Кроме того, если система анимации подчеркнута, иногда Раскадровка. Завершенное событие никогда не генерируется.
Все примеры я приехал через анимационный преобразования от XAML. Документация MSDN предлагает, чтобы x:Name свойство преобразования было установлено, чтобы это было animatable, но я не нашел рабочий способ установить его из кода.
Какие-либо идеи?
Вот полный листинг кода, который воспроизводит проблему:
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 {
///
/// Interaction logic for MainWindow.xaml
///
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());
}
}
}
Похоже, что после небольшого поиска в Google я решил проблему сам. Большое спасибо документации MSDN и за сообщение Antares19 на форумах MSDN.
Вкратце:
Чтобы объект 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());
}
}
}