I tried to create a card game in WPF. My Problem is that I want to flip a card at a certain time. I created two storyboards in a datatemplate, one for each flip (back and front). But when I tried to access and start it from the code behind I got an error, because it can't access the grid, which contains the new card image, inside the datatemplate. So my question is, how can I access the grid inside the datatemplate from code behind, to get my storyboard run?
Here is my code:
XAML:
<Window x:Class="KartenQuartett.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:KartenQuartett"
mc:Ignorable="d"
ResizeMode="NoResize"
Title="{Binding Title}" Height="510" Width="670" WindowStartupLocation="CenterScreen">
<Window.Resources>
<DataTemplate x:Key="RotatingItemTemplate">
<DataTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-1">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)" Storyboard.TargetName="grid1">
<EasingInt32KeyFrame KeyTime="0" Value="0"/>
<EasingInt32KeyFrame KeyTime="0:0:0.5" Value="0"/>
<EasingInt32KeyFrame KeyTime="0:0:0.5" Value="1"/>
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)" Storyboard.TargetName="image">
<EasingInt32KeyFrame KeyTime="0" Value="1"/>
<EasingInt32KeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingInt32KeyFrame KeyTime="0:0:0.5" Value="0"/>
</Int32AnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard1_reversed">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="grid">
<SplineDoubleKeyFrame KeyTime="0" Value="-1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)" Storyboard.TargetName="grid1">
<EasingInt32KeyFrame KeyTime="0:0:0.5" Value="1"/>
<SplineInt32KeyFrame KeyTime="0:0:0.5" Value="0"/>
<SplineInt32KeyFrame KeyTime="0:0:1" Value="0"/>
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.ZIndex)" Storyboard.TargetName="image">
<SplineInt32KeyFrame KeyTime="0:0:0.5" Value="0"/>
<SplineInt32KeyFrame KeyTime="0:0:0.5" Value="1"/>
<SplineInt32KeyFrame KeyTime="0:0:1" Value="1"/>
</Int32AnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<Grid x:Name="grid">
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5"/>
<SkewTransform CenterX="0.5" CenterY="0.5"/>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
<TranslateTransform/>
</TransformGroup>
</Grid.LayoutTransform>
<Grid x:Name="grid1">
<Image x:Name="image1" Source="{Binding ImageFront}" Stretch="Fill" />
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleX="-1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.LayoutTransform>
</Grid>
<Image x:Name="image" Source="{Binding Image}" Stretch="Fill" />
<Button x:Name="Bdrehen" Content="Drehen" HorizontalAlignment="Left" Margin="119,407,0,0" VerticalAlignment="Top" Width="75" Click="Bdrehen_Click"/>
</Grid>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="Bdrehen">
<BeginStoryboard x:Name="Storyboard1_BeginStoryboard1" Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown" SourceName="grid1">
<StopStoryboard BeginStoryboardName="Storyboard1_BeginStoryboard1"/>
<BeginStoryboard x:Name="Storyboard1_reversed_BeginStoryboard" Storyboard="{StaticResource Storyboard1_reversed}"/>
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"></ColumnDefinition>
<ColumnDefinition Width=".5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" x:Name="gridOne">
<Image x:Name="cardFront" Source="Bilder/card_front.png" Stretch="Fill">
</Image>
<StackPanel x:Name="stack1" Margin="25">
</StackPanel>
</Grid>
<Grid Grid.Column="1" x:Name="gridTwo">
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ItemsControl ItemsSource="{Binding MyImages}"
ItemsPanel="{DynamicResource ItemsPanelTemplate1}"
ItemTemplate="{DynamicResource RotatingItemTemplate}">
<ItemsControl.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.Resources>
</ItemsControl>
</ScrollViewer>
<StackPanel x:Name="stack2" Margin="25">
</StackPanel>
</Grid>
</Grid>
So "grid" and "grid1" are the elements, which can't accessed.
For tests i created a button "Bdrehen" to check, if I can access the flip from a button. This works perfect, it also works by left-clicking on it with the mouse. But not by code.
Heres the code, where I try to start it from code behind:
DataTemplate dt = (DataTemplate)FindResource("RotatingItemTemplate");
Storyboard sb = dt.Resources["Storyboard1_reversed"] as Storyboard;
BeginStoryboard(sb);
After starting I got an error, that the "grid" can't be found in the namespace of "KartenQuartett.MainWindow". I can find my storyboards, but not my grids inside the datatemplate.
Anyone got an idea to fix it?
Here is your answer Calling Storyboard inside DataTemplate.
But keep in mind that doing that is not a good idea. Accessing any UI Element from your code behind is not a great idea, because it creates a tight coupling between your code and your UI.
I would suggest you to use MVVM instead, and to bind a boolean to run your storyboard as explained here: How to play Storyboard in ViewModel?