Storyboard et Datatemplate
-
mardi 31 juillet 2012 13:46
Bonjour à tous,
Tout juste débutant dans le dev Windows, je suis en train d'apprendre sur le tas, en réalisant ma première app.
Mon souci vient des animations. J'ai actuellement une itemgridview dont le template est le suivant:<DataTemplate x:Key="DefaultGridItemTemplate"> <Grid HorizontalAlignment="Left" Width="250" Height="250"> <!-- Code à rajouter pour animation --> <Image Source="{Binding Image}" Stretch="UniformTofill"/> <StackPanel x:Name="stackPanel" VerticalAlignment="Bottom" Orientation="Vertical" HorizontalAlignment="Stretch" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" Height="70" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform/> </StackPanel.RenderTransform> <TextBlock Text="{Binding Title}" Style="{StaticResource GridTitleTextStyle}" Foreground="White"/> <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal" HorizontalAlignment="Right"> <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42" Foreground="White"/> <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" Margin="12,4,12,8" Foreground="White"/> </StackPanel> </StackPanel> </Grid> </DataTemplate>Je cherche à avoir une animation du stackpanel de chaque item, un peu comme sur l'appli lemonde (très belle par ailleurs). En passant par blend, le code que j'ai ajouté est:
<Grid.Resources> <Storyboard x:Name="Storyboard1"> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="stackPanel"> <EasingDoubleKeyFrame KeyTime="0" Value="-176.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-0.667"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="stackPanel"> <EasingDoubleKeyFrame KeyTime="0" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </Grid.Resources>
Dans la page code-behind, je fais lance alors l'animation par:
Storyboard sb = this.FindName("Storyboard1") as Storyboard; if (sb!= null) sb.Begin();
Premier problème, sb est toujours null, Storyboard1 n'est pas trouvé !
Qu'a cela ne tienne, j'ai sorti ma définition de storyboard de mon DataTemplate DefaultGridItemTemplate, pour le mettre directement entre les balises Page.Resources.
Cette fois-ci, l'appel au Storyboard depuis la page code-behind est bien fait, mais son targetName (stackPanel) est introuvable....
Je suis un peu perdu, je me doute bien que "l'obstacle" provient du fait que ce stackPanel est défini dans mon dataTemplate....
Merci à vous de prendre le temps de m'éclairer !
- Déplacé Florin CiucaMicrosoft Contingent Staff, Owner vendredi 7 septembre 2012 10:37 (Origine :Développement d’applications de style Metro pour Windows 8)
Toutes les réponses
-
mercredi 1 août 2012 09:14
Supposons que le storyboard (situé dans le DataTemplate) soit déclenché par un clic sur un bouton situé dans la grid.
public void btn_Click(sender as Object, e as ...)
Il faut retrouver une référence à la grid :
var btn = sender as Button;
(pour trouver le parent, y'a un exemple de code ici : http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c47754bd-38c7-40b3-b64a-38a48884fde8/)
Puis, quand vous avez la référence à la Grid :
var sb = gd.Resources["monStoryboard"] as Storyboard;
Maintenant, je ne connais pas votre scénario, mais il serait peut être bon de se pencher sur les VisualStates.
Richard Clark
Consultant - Formateur .NET
http://www.c2i.fr
Depuis 1996: le 1er site .NET francophone -
jeudi 2 août 2012 15:12
Merci de votre réponse.
J'ai essayé de passer par les VisulStates pour résoudre mon problème... mais sans plus de succès ! Je ne sais pas comment indiquer le bon Storyboard.TargetName pour appliquer la transition à chaque stackPanel de chaque item de mon itemGridView ...
<VisualState x:Name="FullScreenLandscape"> <Storyboard> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="stackPanel"> <EasingDoubleKeyFrame KeyTime="0" Value="-176.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:5" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-176.667"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="stackPanel"> <EasingDoubleKeyFrame KeyTime="0" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> -
jeudi 2 août 2012 21:02Le TargetName doit être le nom de votre StackPanel <StackPanel Name="stackpanel"> C'est le cas ?
Richard Clark
Consultant - Formateur .NET
http://www.c2i.fr
Depuis 1996: le 1er site .NET francophone -
vendredi 3 août 2012 15:18
Oui, mais j'ai une erreur lors de l'exécution: Cannot resolve TargetName stackPanel. Il ne trouve pas le chemin jusqu'à la définition de ce stackpanel dans ma itemgridview ...
Pour être plus clair, voici mon code :
<common:LayoutAwarePage x:Name="pageRoot" x:Class="BonjourMashUp.GroupedItemsPage1" DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}" IsTabStop="false" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BonjourMashUp" xmlns:common="using:BonjourMashUp.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <!-- Collection of grouped items displayed by this page, bound to a subset of the complete item list because items in groups cannot be virtualized --> <CollectionViewSource x:Name="groupedItemsViewSource" Source="{Binding Groups}" IsSourceGrouped="true" ItemsPath="Feeds"/> <!-- TODO: Delete this line if the key AppName is declared in App.xaml --> <x:String x:Key="AppName">Bonjour !</x:String> <!-- light blue --> <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#1E7DB7"/> <!-- Grid Styles --> <Style x:Key="GridTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}"> <Setter Property="FontSize" Value="26.667"/> <Setter Property="Margin" Value="12,0,12,2"/> </Style> <Style x:Key="GridDescriptionTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}"> <Setter Property="VerticalAlignment" Value="Bottom"/> <Setter Property="Margin" Value="12,0,12,60"/> </Style> <DataTemplate x:Key="DefaultGridItemTemplate"> <Grid HorizontalAlignment="Left" Width="250" Height="250"> <Image Source="{Binding Image}" Stretch="UniformTofill"/> <StackPanel Name="stack" VerticalAlignment="Bottom" Orientation="Vertical" HorizontalAlignment="Stretch" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" Height="70" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform/> </StackPanel.RenderTransform> <TextBlock Text="{Binding Title}" Style="{StaticResource GridTitleTextStyle}" Foreground="White"/> <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal" HorizontalAlignment="Right"> <Button x:Name="testButton" Click="actioon" Content="test" Width="120" Height="60"/> <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42" Foreground="White"/> <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" Margin="12,4,12,8" Foreground="White"/> </StackPanel> </StackPanel> </Grid> </DataTemplate> </Page.Resources> <!-- This grid acts as a root panel for the page that defines two rows: * Row 0 contains the back button and page title * Row 1 contains the rest of the page layout --> <Grid Style="{StaticResource LayoutRootStyle}"> <Grid.RowDefinitions> <RowDefinition Height="140"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- Back button and page title --> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <StackPanel x:Name="stackPanel" VerticalAlignment="Bottom" Orientation="Vertical" HorizontalAlignment="Stretch" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" Height="70" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform/> </StackPanel.RenderTransform> <TextBlock Text="{Binding Title}" Style="{StaticResource GridTitleTextStyle}" Foreground="White"/> <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal" HorizontalAlignment="Right"> <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42" Foreground="White"/> <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" Margin="12,4,12,8" Foreground="White"/> </StackPanel> </StackPanel> <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/> <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Grid.Column="1" Style="{StaticResource PageHeaderTextStyle}"/> </Grid> <!-- Horizontal scrolling grid used in most view states --> <GridView x:Name="itemGridView" AutomationProperties.AutomationId="ItemGridView" AutomationProperties.Name="Grouped Items" Grid.Row="1" Margin="0,-3,0,0" Padding="116,0,40,46" ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}" ItemTemplate="{StaticResource DefaultGridItemTemplate}" SelectionMode="None" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"> <GridView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Grid Margin="1,0,0,6"> <Button AutomationProperties.Name="Group Title" Content="{Binding Categorie}" Style="{StaticResource TextButtonStyle}" Click="Header_Click"/> </Grid> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> </GridView> <!-- Vertical scrolling list only used when snapped --> <ListView x:Name="itemListView" AutomationProperties.AutomationId="ItemListView" AutomationProperties.Name="Grouped Items" Grid.Row="1" Visibility="Collapsed" Margin="0,-10,0,0" Padding="10,0,0,60" ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}" ItemTemplate="{StaticResource Standard80ItemTemplate}" SelectionMode="None" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"> <ListView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Grid Margin="7,7,0,0"> <Button AutomationProperties.Name="Group Title" Content="{Binding Categorie}" Style="{StaticResource TextButtonStyle}"/> </Grid> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> </ListView> <VisualStateManager.VisualStateGroups> <!-- Visual states reflect the application's view state --> <VisualStateGroup x:Name="ApplicationViewStates"> <VisualState x:Name="FullScreenLandscape"> <Storyboard> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="stack"> <EasingDoubleKeyFrame KeyTime="0" Value="-176.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:5" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-176.667"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="stack"> <EasingDoubleKeyFrame KeyTime="0" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Filled"/> <!-- The entire page respects the narrower 100-pixel margin convention for portrait --> <VisualState x:Name="FullScreenPortrait"> </VisualState> <!-- The back button and title have different styles when snapped, and the list representation is substituted for the grid displayed in all other view states --> <VisualState x:Name="Snapped"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style"> <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style"> <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </common:LayoutAwarePage>Cela fait un moment que je tourne en rond, merci de me sortir de là ;) -
lundi 13 août 2012 13:02
Bonjour,
effectivement ton "stack" fait partie d'un DataTemplate, et là tu es sur le VisualStateManager de la page : stack n'existe pas encore.
Tu as toujours deux approches possible : celle de Grid.Resources + Storyboard qui fonctionne, c'est ton moyen de le récupérer qui n'est pas bon (toujours pour la même raison, la Grid n'existe pas encore), et celle du VisualState.
Dans tous les cas, tu devrais t'abonner à l'évènement Loaded de ta Grid (si par exemple ton animation doit se lancer quand celle-ci se charge).
Pour le Storyboard
Dans l'Event Handler correspondant, tu peux appeler ton storyboard comme ceci :var storyboard = (sender as Grid).Resources["Storyboard1"] as Storyboard; storyboard.Begin();
Pour le VisualState
Déjà, utilise le VisualState lié à la Grid
<DataTemplate x:Key="DefaultGridItemTemplate"> <Grid Loaded="Grid_Loaded_1" HorizontalAlignment="Left" Width="250" Height="250"> <!-- Code à rajouter pour animation --> <Image Source="{Binding Image}" Stretch="UniformTofill"/> <StackPanel x:Name="stack" ...> <!-- LE RESTE TON TON TEMPLATE... --> <VisualStateManager.VisualStateGroups> <!-- Visual states reflect the application's view state --> <VisualStateGroup x:Name="CustomVisualState"> <VisualState x:Name="Loading"> <Storyboard> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="stack"> <EasingDoubleKeyFrame KeyTime="0" Value="-176.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:5" Value="-83.334"/> <EasingDoubleKeyFrame KeyTime="0:0:6" Value="-176.667"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="stack"> <EasingDoubleKeyFrame KeyTime="0" Value="-0.667"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.666"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </DataTemplate>
Ensuite, toujours dans le même Event Handler, tu peux appeler le Visual State Manager.
Comme VisualStateManager.GoToState prend un paramètre de type Control, tu ne pourras pas y passer ta Grid directement, voici un petit workaround :VisualStateGroup vsg = VisualStateManager.GetVisualStateGroups(sender as Grid).First(); vsg.States.First().Storyboard.Begin();
J'ai testé les deux solutions, elle fonctionnent bien, j'dis pas que ce sont des bonne pratiques ensuite :)
Ensuite à toi d'adapter pour lancer ces animations quand tu en as besoin. N'hésite pas à poser de nouvelles question si besoin.
Blog => http://ashworks.fr | Twitter => http://twitter.com/ashura95
- Modifié Alexis MATHIEU lundi 13 août 2012 13:02
- Marqué comme réponse Aurel BeraMicrosoft Contingent Staff, Owner jeudi 13 septembre 2012 10:23
-
jeudi 13 septembre 2012 10:23Propriétaire
Bonjour,
Pouvons-nous considérer que vous avez résolu votre problème avec les scénarios proposés ? Dans l'affirmative, pourriez-vous partager avec nous la solution, afin que d'autres personnes avec le même problème puissent profiter de cette solution ?
Désormais, nous marquons les solutions proposées. N'hésitez pas à revenir et supprimer la réponse marquée si la solution n’est pas correcte. Merci !
Cordialement,
Aurel


