将DataTemplateSelector与ItemContainerStyle一起使用

时间:2016-05-17 17:18:57

标签: xaml gridview uwp uwp-xaml

我有GridView使用DataTemplateSelector。在DataTemplateSelector上设置GridView时,它可以正常工作:

        <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>

但是,我正在尝试在DataTemplate内设置ItemContainerStyle,以便我可以使用VisualStateManager。我试着像这样声明:

        <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>

使用ContentPresenter并以与ContentTemplateSelector相同的方式指定ItemTemplateSelector GridView。这样做,GridView只显示每个Payee的对象视图。 VisualStates正常工作,但未使用我定义的DataTemplate

DataTemplates定义Page.Resources,如此:

    <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}" />

或者,我尝试使用VisualStateManager内的DataTemplate,但它们未被触发,因此我需要在外使用 DataTemplate,因此希望在ContentPresenter内使用ItemContainerStyle

我对某些ListViewItem执行类似操作,但他们不使用DataTemplateSelector,因此我不会遇到同样的问题。有没有办法让VisualStateManagerDataTemplate内工作,或让DataTemplateSelectorContentPresenter内工作?

修改

这是我尝试放入Styles/DataTemplates.xaml的XAML。正在应用该样式,但我没有触发任何VisualStates

<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>

VisualState直接使用GridView.ItemContainerStyle设置Template时工作正常,但在单独的资源文件中从DataTemplate尝试时却不行。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

在内容模板选择器上不确定。 但是,您最初在DataTemplates中使用VisualStateManager的想法应该有效。

尝试此操作时,您错过了一件事,您需要将DataTemplate中的所有内容都包含在UserControl标记中!否则VisualStateManager将无效。

此处的示例:https://github.com/AppCreativity/Kliva/blob/master/src/Kliva/XAMLResources/DataTemplates.xaml#L21

答案 1 :(得分:0)

我可以通过在ContentTemplate内的ContentPresenter上设置ItemTemplate来实现我想要的效果,如下所示:

    <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>

当然,PaymentTemplateDataTemplate中定义的DataTemplates.xaml。理想情况下,我希望将VisualStateManager内容与DataTemplate本身捆绑在一起,以便在我的View中整理XAML,但这种方式现在适用。