Хотя XAML не зависит от WPF, визуальные элементы - нет. В частности, анимация и макет являются частью WPF и зависят от присутствия в нем WPF - через объект приложения, PresentationSource, такой как HwndSource, XBAP PresentationHost.exe и т. Д.
Таким образом, вы можете читать в своем XAML и получать граф объектов объекта Test с дочерним объектом Storyboard, но этот объект Test не подключается к механизмам анимации или компоновки, пока не будет помещен в контекст WPF. Все, что XAML получает от вас, - это тупой граф объектов в памяти: это WPF, а не XAML, который делает объекты «живыми».
Так что, как говорит Бен, вам, вероятно, в конечном итоге понадобится «толкать или подталкивать» анимацию самостоятельно. Я не знаю какой-либо документации о том, как это сделать, но из возни в Reflector похоже, что ключевым API является Storyboard.SeekAlignedToLastTick , о котором в документах говорится:
Значения немедленно обновляются до
отражать изменения, вызванные
SeekAlignedToLastTick, даже если
экран не отражает эти изменения
пока экран не обновится.
Обратите внимание на это второе предложение. Обычно WPF обрабатывает обновление экрана при изменении значений визуального объекта. Если вы не используете WPF, то вам нужно прочитать измененные значения и соответствующим образом перерисовать экран: у вас нет менеджера макета WPF, который бы его обрабатывал.
Наконец, обратите внимание, что я не проверял, будет ли SeekAlignedToLastTick работать в среде без загруженной сантехники WPF. Это звучит , как и должно быть, потому что это не заботится о том, управляет ли часами WPF или пользовательский код, но я не могу давать никаких обещаний ... хотя я признаю, что вы заинтересовали меня !
ОБНОВЛЕНИЕ: Я сделал это быстро, и, похоже, это работает. Вот демонстрация размещения анимации в Windows Forms (в данном случае с использованием обычного таймера Windows Forms, но в XNA я предполагаю, что фреймворк предоставит вам игровой таймер - не пробовал, потому что я не знаю XNA). Предположим, у вас есть ванильная форма Windows с таймером (timer1) и меткой (label1), и что проект ссылается на сборки WPF.
Во-первых, моя упрощенная версия вашего класса:
[ContentProperty("Animation")]
public class Fie : DependencyObject
{
public double Test
{
get { return (double)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(double), typeof(Fie),
new FrameworkPropertyMetadata(0.0));
public Storyboard Animation { get; set; }
}
Теперь код WPF для загрузки одного из этих детей из XAML и запуска анимации:
private Fie _f;
private DateTime _startTime;
public Form1()
{
InitializeComponent();
string xaml =
@"<local:Fie xmlns:local=""clr-namespace:AnimationsOutsideWpf;assembly=AnimationsOutsideWpf""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty=""Test""
From=""0""
To=""360""
Duration=""00:00:10.0""/>
</Storyboard>
</local:Fie>";
_f = (Fie)XamlReader.Load(XmlReader.Create(new StringReader(xaml)));
Storyboard.SetTarget(_f.Animation, _f);
_f.Animation.Begin();
_startTime = DateTime.Now;
timer1.Enabled = true;
}
Обратите внимание, что я должен был установить цель раскадровки как объект XAML, который только что загрузил. Это не происходит автоматически. Я пытался сделать это с Storyboard.TargetName в XAML, но это не сработало - возможно, вам повезет больше.
Последние строки просто настроены для обратного вызова таймера:
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan sinceStart = DateTime.Now - _startTime;
_f.Animation.SeekAlignedToLastTick(sinceStart);
label1.Text = _f.Test.ToString();
}
Я сохранил время начала анимации и использовал его, чтобы вычислить, насколько далеко мы дошли до анимации. Таймеры WinForms немного грубоваты, но этого достаточно для доказательства концепции; без сомнения, у XNA будет что-то лучше. Затем я вызываю Storyboard.SeekAlignedToLastTick, которая обновляет анимированные значения. Ничего не отображается автоматически, потому что мой объект XAML не подключен для отображения, но я могу проверить его свойство Test и убедиться, что он действительно анимируется. В действительности, я бы использовал это для обновления положения или ориентации любого визуального элемента XNA, представленного объектом XAML.