mardi 27 janvier 2015

ObservableColection and Animations in EventHandlers


Background


I'm writing a Windows Store app in C# / XAML that incorporates multiple ObservableCollections. The elements in these collections subscribe to a number of Events to start a variety of Storyboard animations defined in XAML. This all works fine so long as I manually Add the elements to panels defined in XAML: the elements get displayed and animate as intended e.g. when tapped.


What I’m trying to do


But this misses the point about some of the great powers of the ObservableCollection: when the collection changes (e.g. elements added or removed) I still have to manually reflect this in the corresponding panel. As I understand it, the solution is to connect the ObservableCollections to the panels using Data Binding so that these panels get updated dynamically whenever a collection changes. I think I also understand that doing this with a StackPanel requires an ItemsControl (because StackPanel doesn’t have ItemSource…?)


Where I get stuck


Where I get stuck is with the animations: whatever I try, data binding the panels with the collections somehow causes a ‘Cannot resolve TargetName’ error that wasn’t a problem before.


What is a correct way to change my example code below so that MyStackPanel is connected to the MyBuilding ObservableCollection using Data Binding? Any help very much appreciated.


XAML



<Page
x:Class="MyApp.MainPage"
xmlns="http://ift.tt/o66D3f"
xmlns:x="http://ift.tt/mPTqtT"
xmlns:local="using:MyApp"
xmlns:d="http://ift.tt/pHvyf2"
xmlns:mc="http://ift.tt/pzd6Lm"
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>


Code behind



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




Aucun commentaire:

Enregistrer un commentaire