WPF ListViewItem选中触发器设置Background属性不生效问题
问题原因
ListViewItem默认控件模板内置了系统主题定义的选中态视觉渲染逻辑,选中时模板层会强制用主题默认的高亮画刷渲染背景、边框,直接覆盖你在Style触发器里设置的Background、BorderBrush这类画刷属性。BorderThickness没有被模板逻辑强制重写,所以对应的设置可以正常生效。
修复方案
有两种可行的修复方式,根据需求选择即可:
- 方案一:重写
ListViewItem控件模板(推荐,兼容性最好)
直接替换默认模板,移除内置的选中态强制画刷覆盖逻辑,自定义的样式可以完全生效,参考代码如下:
<Window x:Class="ListViewTest.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:ListViewTest" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <ListView BorderThickness="0"> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListViewItem}"> <Border x:Name="ItemBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="ItemBorder" Property="Background" Value="Red"/> <Setter TargetName="ItemBorder" Property="BorderThickness" Value="0"/> </Trigger> <!-- 按需保留鼠标悬停效果,不需要可删除 --> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="ItemBorder" Property="Background" Value="#FFF5F5F5"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListView.ItemContainerStyle> <ListViewItem Content="Just a test"/> <ListViewItem Content="Another test"/> </ListView> </Grid> </Window>
- 方案二:覆盖系统主题画刷键(代码更简洁)
不需要重写模板,直接在ListView资源中替换系统默认选中态对应的画刷资源即可:
<ListView BorderThickness="0"> <ListView.Resources> <!-- 选中聚焦状态的背景色 --> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/> <!-- 选中文本颜色 --> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/> <!-- 选中失焦状态的背景色 --> <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red"/> </ListView.Resources> <!-- 原有ItemContainerStyle和ListViewItem代码保持不变即可 --> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="BorderThickness" Value="0"/> </Trigger> </Style.Triggers> </Style> </ListView.ItemContainerStyle> <ListViewItem Content="Just a test"/> <ListViewItem Content="Another test"/> </ListView>
注意:方案二依赖系统主题的资源键定义,在部分高对比度系统主题、自定义Windows主题下可能出现样式不生效的问题,需要兼容多场景的话优先选择方案一。
内容的提问来源于stack exchange,提问作者Franz Gsell
相关产品推荐
相关产品推荐

