Введение
Я пишу программу с классом карты, который содержит фоновое изображение и список (ObservableCollection) узлов, которые имеют свойства цвета, местоположения и анимации. Приложение WPF поверх этого имеет ссылку
Задача
У меня есть объект типа GameMapModel, который содержит наблюдаемую коллекцию типа GameMapNode:
[AddINotifyPropertyChangedInterface]
public class GameMapModel
{
public ObservableCollection<GameMapNode> GameMapNodes { get; set; } = new ObservableCollection<GameMapNode>();
public GameMapNode SelectedNode { get; set; }
public BitmapImage Background { get; set; } = GameMap.jpg; //Link removed for forum post.
public GameMapModel()
{
//SelectedNode = new GameMapNode(0, 0, Brushes.White, "Default");
}
}
[AddINotifyPropertyChangedInterface]
public class GameMapNode
{
public int X { get; set; } = 0;
public int Y { get; set; } = 0;
public Brush Colour { get; set; } = Brushes.Gray;
public string Name { get; set; } = "Default";
public bool Pulse { get; set; } = false;
public bool Spin { get; set; } = false;
public bool Throb { get; set; } = false;
public bool Bounce { get; set; } = false;
public GameMapNode(int x, int y, Brush colour, String name)
{
X = x;
Y = y;
//Colour = colour;
Name = name;
}
public void ChangeTeam()
{
if (Colour == Brushes.Blue)
{
Colour = Brushes.Red;
Spin = true;
Bounce = true;
Pulse = true;
Throb = true;
}
else
{
Colour = Brushes.Blue;
Spin = false;
Bounce = false;
Pulse = false;
Throb = false;
}
}
}
Затем у меня есть UserControl, который отображает фон карты и узлы на основе содержимого GameMapModel:
<Grid Grid.Column="1" Name="MapGrid" MouseMove="Grid_MouseMove" MouseUp="Grid_MouseUp" Width="{Binding GameMap.Background.Width}" Height="{Binding GameMap.Background.Height}" Background="Black">
<Image Source="{Binding GameMap.Background}" Stretch="Fill"/>
<ItemsControl ItemsSource="{Binding GameMap.GameMapNodes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Name="MapCanvas" Width="{Binding Background.Width}" Height="{Binding Background.Height}" MinHeight="240" MinWidth="320" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<!-- <Rectangle x:Name="rect2" Stroke="{Binding GameMap.Colour}" StrokeThickness="20" Width="10" Height="10" /> -->
<Rectangle x:Name="rect1" Stroke="{Binding Colour}" MouseRightButtonDown="Rectangle_MouseRightButtonDown" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" StrokeThickness="20" Width="10" Height="10">
<Rectangle.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="noFreeze" CenterX="5" CenterY="5"/>
<TranslateTransform x:Name="noFreeze2" />
<ScaleTransform x:Name="NoFreeze3" CenterX="5" CenterY="5"/>
</TransformGroup>
</Rectangle.RenderTransform>
<Rectangle.Style >
<Style TargetType="Rectangle" x:Name="RectangleStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Pulse}" Value="True" x:Name="PulseDataTrigger">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="PulseAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="PulseAnimation"/>
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Spin}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="SpinAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" To="-360" Duration="0:0:4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="SpinAnimation"/>
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Bounce}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="BounceAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)" From="5" To="-5" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="BounceAnimation"/>
</DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding Throb}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="ThrobAnimation">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[2].(ScaleTransform.ScaleX)" From="1" To="2" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[2].(ScaleTransform.ScaleY)" From="1" To="2" Duration="0:0:1" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="ThrobAnimation"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
Теперь все это прекрасно работает ЕСЛИ Spin, Bounce и Throb ложны, когда я создаю новый экземпляр GameMapNode и добавляю в коллекцию, после этого я могу установить для любого и все значение true и анимации работают как и ожидалось.
Если во время создания объекта я установлю любое из этих 3 в значение true, я получу следующую ошибку, и программа вылетит:
System.Windows.Markup.XamlParseException: свойство '[Unknown]' не указывает на объект DependencyObject в пути '(0). (1) [0]. (2)'. '
Если я закомментирую блоки анимации Spin / Throb / Bounce DoubleAnimation в XAML, анимация не будет работать, но программа не вылетит.
То же самое НЕ верно для анимации «Непрозрачность», которая прекрасно работает, даже если для Pulse установлено значение true во время создания объекта.
Это заставляет меня думать, что что-то связано с реализацией TransformGroup, поскольку это НЕ используется для импульса. Может быть, они не загружены до первой попытки DataTrigger?
Это мое первое настоящее приложение WPF, и у меня есть отличный наставник, помогающий мне в этом, но даже он в замешательстве. Любая помощь предложений будет принята с благодарностью:)