需求
最近在做的一个小工具中用到了ListView来显示一些数据。但是ListView默认的样式不太符合个人的审美,于是想修改ListView子项的各种效果。
尝试过程
阶段1 自己摸索
按照以往对于控件样式修改的流程来说,应该是选择这个控件,然后创建它的模板,通过修改模板来达到效果。
例如ListBox中选择项的修改方式就是:
可是ListView的结构并不是这样的,虽然在XAML代码中设置了ListView.View
属性,但是ListView内部并没有一个ListViewItem可以让我们来编辑模板。
阶段2 查找别人的解决方案
既然按照自己以往的处理方式并不能解决问题,那么就只好去搜索一下如何修改了。
在国内外的搜索引擎上都尝试过搜索了,能看到最常用的处理方式是:
<ListView x:Name="listView2">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="Orange" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="BorderThickness" Value="10"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Pink" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="Purple" />
<Setter Property="BorderThickness" Value="5"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="ColumnA" DisplayMemberBinding="{Binding Path=A}"/>
<GridViewColumn Header="ColumnB" DisplayMemberBinding="{Binding Path=B}"/>
<GridViewColumn Header="ColumnC" DisplayMemberBinding="{Binding Path=C}"/>
<GridViewColumn Header="ColumnD" DisplayMemberBinding="{Binding Path=D}"/>
</GridView>
</ListView.View>
</ListView>
(上述的Style也可以设置给ListView.ItemContainerStyle
属性)
这样做虽然起效了,可是只能修改一部分内容的样式,其他部分(例如中间有一层渐变色)却无从修改:
因此这个方法并不能达到我的要求。
阶段3 再次摸索(解决问题)
在继续尝试对控件进行创建模板的时候,我突然发现一个选项:
点击后,会在ListView中添加一个ListViewItem,然后对着这个ListViewItem右键就可以创建模板了!
那这样不就可以修改模板到自己想要的样式,然后设置给ListView.ItemContainerStyle
属性了吗?
<ListView x:Name="listView3" ItemContainerStyle="{DynamicResource ListViewItemStyle1}">
<ListView.View>
<GridView>
<GridViewColumn Header="ColumnA" DisplayMemberBinding="{Binding Path=A}"/>
<GridViewColumn Header="ColumnB" DisplayMemberBinding="{Binding Path=B}"/>
<GridViewColumn Header="ColumnC" DisplayMemberBinding="{Binding Path=C}"/>
<GridViewColumn Header="ColumnD" DisplayMemberBinding="{Binding Path=D}"/>
</GridView>
</ListView.View>
</ListView>
然而事情并没有那么顺利,最终程序显示的效果出现了问题:
每行的样式确实是变了,但每行显示的内容却出现了问题,与我们想要的表格是不一样的,只显示了一个内容。
这又是为什么呢?
于是只好再去搜索引擎上查找,看有没有能解决的方案。最终看到了这样一个帖子:
这样就明白了!ListViewItem内部应该使用GridViewRowPresenter
组件,而并非是创建副本时给的ContentPresenter
!
只要在模板中把控件改变一下就好了!
原本是:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
修改为:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
再次运行程序:
收工!