是否可以在GridView模式下隐式设置WPF ListView的样式?

时间:2013-02-16 21:46:39

标签: wpf styles skinning

我可以在基本(非GridView)模式下轻松“隐式”设置ListView样式,但是我在GridView模式下隐式设置ListView样式的尝试却失败了。下面的工作原理是因为我明确设置了第二个ListView的Style和ItemContainerStyle。如果删除这两个设置,则第二个ListView不会像第一个那样进行隐式设置。似乎基本的ListView需要ContentPresenter,而GridView ListView需要GridViewRowPresenter。

我在这里跑进WPF砖墙吗?这甚至可能吗?如果没有,它会使创建应用程序外观不那么健壮,因为现在您的用户必须知道在GridView模式下显示的ListViews上显式设置Style和ItemContainerStyle。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="ListView">
            <Setter Property="Background" Value="Lime"/>
        </Style>
        <Style TargetType="ListViewItem">
            <Setter Property="Background" Value="Yellow"/>
            <Setter Property="Template">
              <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Grid>
                      <ContentPresenter x:Name="ContentHost" Margin="{TemplateBinding Padding}"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                    </Grid>
                </ControlTemplate>
              </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="{x:Static GridView.GridViewStyleKey}"
               TargetType="{x:Type ListView}">
            <Setter Property="Background" Value="Lime"/>
        </Style>
        <Style x:Key="{x:Static GridView.GridViewItemContainerStyleKey}"
               TargetType="{x:Type ListViewItem}">
            <Setter Property="Background" Value="Yellow"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView x:Name="_listView1">
            <system:String>Item 1</system:String>
            <system:String>Item 2</system:String>
            <system:String>Item 3</system:String>
        </ListView>

        <ListView x:Name="_listView2" Grid.Column="1" 
                  Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"
                  ItemContainerStyle="{StaticResource {x:Static GridView.GridViewItemContainerStyleKey}}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Date"/>
                    <GridViewColumn Header="Day of Week" DisplayMemberBinding="{Binding DayOfWeek}" />
                    <GridViewColumn Header="Year" DisplayMemberBinding="{Binding Year}" />
                </GridView>
            </ListView.View>
            <system:DateTime>1/1/2010</system:DateTime>
            <system:DateTime>1/1/2011</system:DateTime>
            <system:DateTime>1/1/2012</system:DateTime>
        </ListView>
    </Grid>
</Window>

1 个答案:

答案 0 :(得分:4)

我遇到了与你上面描述的相同的奇怪/棘手的问题,然后遇到了一篇博文,其中提出了一个简洁的小黑客/修复方法,它似乎提供了你所追求的行为。如果链接死亡,重复要点。

如果您想要使用ListView覆盖视图并使用GridViews,您已经描述了ListView样式的奇怪要求;基本ContentPresenter需要GridView ListView needsGridViewRowPresenterSetter

海报设法通过在他的风格中包括两位演示者并使用ContentPresenter仅在需要时显示ControlTemplate来解决这个问题。

所以你的<ControlTemplate TargetType="{x:Type ListBoxItem}"> <!-- Pair of presenters --> <Grid> <GridViewRowPresenter x:Name="gridrowPresenter" Content="{TemplateBinding Property=ContentControl.Content}"/> <ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Property=ContentControl.Content}" Visibility="Collapsed"/> </Grid> <!-- Visibility Controlling Setter --> <ControlTemplate.Triggers> <Trigger Property="GridView.ColumnCollection" Value="{x:Null}"> <Setter TargetName="contentPresenter" Property="Visibility" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> 可以按照这些方式实现某些功能(根据需要添加额外的样式属性):

GridViewRowPresenter

样式中存在ContentPresenterContentPresenter,但Visibility="Collapsed"被隐藏(Trigger)。

巧妙的诀窍是在GridView.ColumnCollection上使用GridViewRowPresenter;如果此值为null(在ContentPresenter没有内容时发生),则ListView将变为可见,正确显示您的正常GridViewRowPresenter内容。 GridView没有内容,因此不会显示任何有冲突的视觉效果。

如果ContentPresenter包含内容,则会显示(提供正确的行格式),{{1}}将保持隐藏状态。

原创博客文章:http://www.steelyeyedview.com/2010/03/contentpresenter-gridviewrowpresenter.html