背景
我在C#/ XAML中编写了一个包含多个ObservableCollections的Windows应用商店应用。这些集合中的元素订阅了许多事件,以启动XAML中定义的各种Storyboard动画。 只要我手动将元素添加到XAML中定义的面板,这一切都可以正常工作:元素会按预期显示和动画,例如点击时。
我正在尝试做什么
但是这忽略了ObservableCollection的一些强大功能:当集合发生变化时(例如添加或删除元素),我仍然需要在相应的面板中手动反映这一点。 据我了解,解决方案是使用数据绑定将ObservableCollections连接到面板,以便在集合更改时动态更新这些面板。我想我也明白用StackPanel做这个需要一个ItemsControl(因为StackPanel没有ItemSource ......?)
我遇到的地方
我卡住的地方是动画:无论我尝试什么,数据绑定面板与集合以某种方式导致'无法解决TargetName '错误之前没有问题。
更改下面的示例代码的正确方法是什么,以便MyStackPanel使用数据绑定连接到MyBuilding ObservableCollection?非常感谢任何帮助。
XAML
<Page
x:Class="MyApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Storyboard x:Name="TappedAnimation">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="-15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel x:Name="MyStackPanel" Grid.Column="0"/>
</Grid>
</Page>
代码
namespace MyApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Button[] MyBrick = new Button[4];
ObservableCollection<Button> MyBuilding = new ObservableCollection<Button>();
for (int i = 0; i < 4; i++)
{
MyBrick[i] = new Button();
MyBrick[i].Content = "My Button " + (i+1).ToString();
MyBrick[i].Name = "MyButton" + (i + 1).ToString();
MyBrick[i].ManipulationMode = ManipulationModes.All;
MyBrick[i].RenderTransformOrigin = new Point(0.5, 0.5);
MyBrick[i].RenderTransform = new CompositeTransform();
MyBrick[i].Tapped += new TappedEventHandler(brick_Tapped);
MyBuilding.Add(MyBrick[i]);
MyStackPanel.Children.Add(MyBrick[i]);
}
MyBuilding.Remove(MyBrick[2]); // how to get this dynamically reflected in MyStackPanel?
}
private void brick_Tapped(object sender, TappedRoutedEventArgs e)
{
TappedAnimation.Stop();
TappedAnimation.SetValue(Storyboard.TargetNameProperty, (sender as Button).Name);
TappedAnimation.Begin();
}
}
}