Reputation: 3342
I have a GridView
that uses a DataTemplateSelector
. It works fine when the DataTemplateSelector
is set on the GridView
like so:
<GridView x:Name="PayeesGridView"
IsItemClickEnabled="True"
ItemTemplateSelector="{StaticResource PayeeTemplateSelector}"
ItemsSource="{Binding FilteredPayees,
Mode=OneWay}"
Padding="5"
SelectionMode="None">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ItemClick">
<core:CallMethodAction MethodName="GridViewItemClick" TargetObject="{Binding Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid x:Name="ItemWrapGrid" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="5" />
</Style>
</GridView.ItemContainerStyle>
</GridView>
However, I am trying to set the DataTemplate
inside of the ItemContainerStyle
so that I am able to use VisualStateManager
. I tried to declare it like this:
<GridView x:Name="PayeesGridView"
IsItemClickEnabled="True"
ItemsSource="{Binding FilteredPayees,
Mode=OneWay}"
Padding="5"
SelectionMode="None">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ItemClick">
<core:CallMethodAction MethodName="GridViewItemClick" TargetObject="{Binding Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid x:Name="ItemWrapGrid" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Grid>
<Grid.Background>
<SolidColorBrush x:Name="GridBackground" Color="Transparent" />
</Grid.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="GridBackground.Color" Value="Green" />
</VisualState.Setters>
<Storyboard />
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="GridBackground.Color" Value="#36B536" />
</VisualState.Setters>
<Storyboard />
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{StaticResource PayeeTemplateSelector}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ItemContainerStyle>
</GridView>
Using a ContentPresenter
and specifying the ContentTemplateSelector
the same way as the ItemTemplateSelector
was on the GridView
. Doing it this way, the GridView
just displays the object view of each Payee
. The VisualStates
work properly, but it is not using the DataTemplate
s that I have defined.
The DataTemplates
are defined in the Page.Resources
like so:
<DataTemplate x:Key="OpenPayeeDataTemplate" x:DataType="models:Payee">
<Grid>
<Border Width="230"
Height="230"
Background="White"
BorderBrush="#36B536"
BorderThickness="4">
<Grid Margin="5,0,5,0">
<Image Width="160"
Height="160"
Source="{x:Bind LogoBase64, Converter={StaticResource Base64StringToImageSourceConverter}}" />
<TextBlock VerticalAlignment="Top"
FontSize="14"
FontWeight="Bold"
Foreground="Black"
Text="{x:Bind CompanyName}"
TextAlignment="Left"
TextWrapping="WrapWholeWords" />
<TextBlock VerticalAlignment="Bottom"
FontSize="12"
FontWeight="Bold"
Foreground="Black"
Text="{x:Bind AccountNickname}"
TextAlignment="Right"
TextWrapping="WrapWholeWords" />
</Grid>
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ClosedPayeeDataTemplate" x:DataType="models:Payee">
<Grid>
<Border Width="230"
Height="230"
Background="White"
BorderBrush="#36B536"
BorderThickness="4">
<Grid Margin="5,0,5,0">
<Image Width="160"
Height="160"
Source="{x:Bind LogoBase64, Converter={StaticResource Base64StringToImageSourceConverter}}" />
<TextBlock VerticalAlignment="Top"
FontSize="14"
FontWeight="Bold"
Foreground="Black"
Text="{x:Bind CompanyName}"
TextAlignment="Left"
TextWrapping="WrapWholeWords" />
<TextBlock VerticalAlignment="Bottom"
FontSize="12"
FontWeight="Bold"
Foreground="Black"
Text="{x:Bind AccountNickname}"
TextAlignment="Right"
TextWrapping="WrapWholeWords" />
</Grid>
</Border>
<Border Width="230"
Height="230"
Background="Gray"
Opacity="0.75" />
</Grid>
</DataTemplate>
<converters:PayeeDataTemplateSelector x:Name="PayeeTemplateSelector"
ClosedPayeeDataTemplate="{StaticResource ClosedPayeeDataTemplate}"
OpenPayeeDataTemplate="{StaticResource OpenPayeeDataTemplate}" />
Alternatively, I have tried to use the VisualStateManager
inside the DataTemplate
s, but they aren't triggered, so I am required to use it outside of the DataTemplate
, hence the desire to use the ContentPresenter
inside the ItemContainerStyle
.
I do something similar with some ListViewItem
s, but they do not use a DataTemplateSelector
so I don't run into the same issue. Is there a way to get VisualStateManager
to work from within a DataTemplate
, or get the DataTemplateSelector
to work from within a ContentPresenter
?
EDIT
Here is the XAML I tried putting in Styles/DataTemplates.xaml
. The style is being applied, but I do not get any of the VisualStates
being triggered.
<DataTemplate x:Key="PaymentTemplate">
<UserControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="GridItemOverlay.Background" Value="Green" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Width="450"
Height="Auto"
Background="White"
BorderBrush="#36B536"
BorderThickness="4"
CornerRadius="5">
<Grid Margin="10,5,10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="34" />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
FontSize="26"
FontWeight="Bold"
Foreground="Black"
Text="{Binding AccountName}"
TextAlignment="Left"
TextWrapping="WrapWholeWords" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Foreground="Black"
Text="{Binding Path=Description}"
TextAlignment="Left" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Foreground="Black">
<Run Text="Payment Amount: " />
<Run Text="{Binding Path=PaymentAmount, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:N}'}" />
</TextBlock>
<TextBlock Grid.Row="2"
Grid.Column="1"
Foreground="Black">
<Run Text="Principal Amount: " />
<Run Text="{Binding Path=PrincipalAmount, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:N}'}" />
</TextBlock>
<TextBlock Grid.Row="3"
Grid.Column="0"
Foreground="Black">
<Run Text="Payment Date: " />
<Run Text="{Binding PaymentDate, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:MM/dd/yyyy}'}" />
</TextBlock>
<TextBlock Grid.Row="3"
Grid.Column="1"
Foreground="Black">
<Run Text="Interest Amount: " />
<Run Text="{Binding Path=InterestAmount, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:N}'}" />
</TextBlock>
</Grid>
</Border>
<Border x:Name="GridItemOverlay"
Background="Transparent"
Opacity="0.50" />
</Grid>
</UserControl>
</DataTemplate>
The VisualState
s work perfectly fine when set directly using the GridView.ItemContainerStyle
to set the Template
, but not when trying it from a DataTemplate
in a separate resource file. Any ideas?
Upvotes: 1
Views: 522
Reputation: 3342
I am able to achieve what I am wanting by setting the ContentTemplate
on a ContentPresenter
inside of my ItemTemplate
, like this:
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="GridItemOverlay.Background" Value="Green" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter ContentTemplate="{StaticResource PaymentTemplate}" />
<Border x:Name="GridItemOverlay"
Background="Transparent"
Opacity="0.50" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ItemContainerStyle>
And of course, PaymentTemplate
is a DataTemplate
defined in DataTemplates.xaml
. Ideally, I would like to get the VisualStateManager
stuff bundled together with the DataTemplate
itself to unclutter the XAML in my View
, but this way works for now.
Upvotes: 0
Reputation: 6142
Not sure on the content template selector.
But, your initial thought on using VisualStateManager
inside the DataTemplates should work.
There is one thing you missed when trying this out, you need to wrap everything inside the DataTemplate
in an UserControl
tag! Otherwise the VisualStateManager
will not work.
Example found here: https://github.com/AppCreativity/Kliva/blob/master/src/Kliva/XAMLResources/DataTemplates.xaml#L21
Upvotes: 2