关闭选择

是否可以关闭 WPF ListView的选择,这样当用户单击行时,该行不会突出显示?

ListView

我希望单击时第1行看起来与第0行一样。

可能相关: 我可以设计悬停/选择的外观吗?例如,用自定义的纯色替换蓝色渐变悬停外观(第3行)。我已经找到了 这个这个,不幸的是没有帮助。

(不使用 ListView 也可以达到同样的效果。我只是希望能够像 ListView 一样使用逻辑滚动和 UI 虚拟化)

ListView 的 XAML 是:

<ListView Height="280" Name="listView">
<ListView.Resources>
<!-- attempt to override selection color -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightColorKey}"
Color="Green" />
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<!-- more columns -->
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
128019 次浏览

根据 Martin Konicek 的评论,以最简单的方式完全禁用项目的选择:

<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>

然而,如果你仍然需要 ListView 的功能,比如能够选择一个项目,那么你可以像这样直观地禁用选中项目的样式:

您可以通过多种方式实现这一点,从更改 ListViewItem 的 ControlTemplate到仅仅设置样式(要容易得多)。您可以使用 ItemContainerStyle为 ListViewItems 创建样式,并在选择背景和边框笔刷时“关闭”它。

<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="{x:Null}" />
<Setter Property="BorderBrush"
Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>

此外,除非您有其他方法在选择项目时通知用户(或者只是为了测试) ,否则您可以添加一列来表示值:

<GridViewColumn Header="IsSelected"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />

继上面的解决方案之后... 我将使用 MultiTrigger 来允许 MouseOver 高光在选择后继续工作,这样您的 ListViewItem 的样式将是:

        <ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
<Condition Property="IsMouseOver" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>

摩尔的回答不起作用,这里有一页:

为列表框中的项指定选择颜色、内容对齐方式和背景颜色

解释了为什么它不能工作。

如果您的列表视图只包含基本文本,那么解决这个问题的最简单方法是使用透明画笔。

<Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#00000000"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#00000000"/>
</Style.Resources>
</Style>
</Window.Resources>

如果 listview 的单元格持有诸如 combobox 之类的控件,这将产生不希望看到的结果,因为它还会改变它们的颜色。若要解决此问题,必须重新定义控件的模板。

  <Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border SnapsToDevicePixels="True"
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Columns="{TemplateBinding GridView.ColumnCollection}"
Content="{TemplateBinding Content}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

下面是 Blend 中 ListViewItem 的默认模板:

默认 ListViewItem 模板:

        <Setter Property="Template">
<Setter.Value>
<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.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

只需删除 IsSelected Trigger 和 IsSelected/IsSelectionActive MultiTrigger,将以下代码添加到您的 Style 中以替换默认模板,当选择时将不会有任何可视化更改。

关闭 IsSelected 属性的可视更改的解决方案:

    <Setter Property="Template">
<Setter.Value>
<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.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

将每个 ListViewItem 的样式设置为 Focus 设置为 false。

<ListView ItemsSource="{Binding Test}" >
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>

我发现最简单的方法是:

<Setter Property="Focusable" Value="false"/>

Listview 的属性之一是 IsHitTestVisible。 取消检查。

好吧,有点晚了,但这些解决方案都没有达到我想要的效果。 这些解决方案存在一些问题

  1. 禁用 ListViewItem,它会打乱样式并禁用所有子控件
  2. 从命中测试堆栈中删除,也就是说,子控件永远不会得到鼠标悬停或单击
  3. 让它无法集中注意力,这只是不适合我吗?

我想要一个带有分组标题的 ListView,每个 ListViewItem 应该只是“信息性”的,没有选择或悬停,但 ListViewItem 有一个按钮,我想要点击和悬停。

所以,我真正想要的是 ListViewItem 根本不是 ListViewItem,所以,我过度使用了 ListViewItem 的 ControlTemplate,只是将它设置为一个简单的 ContentControl。

<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ContentControl Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>

这是为其他可能遇到下列要求的人准备的:

  1. 完全替换“选定”的视觉指示(例如使用某种形状) ,而不仅仅是改变标准高光的颜色
  2. 在 DataTemplate 中包含此选定的指示以及模型的其他可视化表示,但是,
  3. 不希望必须向模型类添加“ IsSelectedItem”属性,并且必须手动操作所有模型对象上的该属性。
  4. 要求在 ListView 中选择项
  5. 还想替换 IsMouseOver 的可视化表示

如果你喜欢我(使用 WPF 与。NET 4.5) ,发现包含样式触发器的解决方案根本不起作用,下面是我的解决方案:

以样式替换 ListViewItem 的 ControlTemplate:

<ListView ItemsSource="{Binding MyStrings}" ItemTemplate="{StaticResource dtStrings}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>

还有数据模板:

<DataTemplate x:Key="dtStrings">
<Border Background="LightCoral" Width="80" Height="24" Margin="1">
<Grid >
<Border Grid.ColumnSpan="2" Background="#88FF0000" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsMouseOver, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}"/>
<Rectangle Grid.Column="0" Fill="Lime" Width="10" HorizontalAlignment="Left" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}" />
<TextBlock Grid.Column="1" Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
</Grid>
</Border>
</DataTemplate>

在运行时的结果(项目‘ B’被选中,项目‘ D’被鼠标悬停) :

ListView appearance

使用以下代码:

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>

下面的代码禁用 ListViewItem 行选择,还允许添加空白、边距等。

<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ListViewItem Padding="0" Margin="0">
<ContentPresenter />
</ListViewItem>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>

下面的代码禁用 Focus on ListViewItem

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

        <ListView Grid.Row="1" ItemsSource="{Binding Properties}" >
<!--Disable selection of items-->
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid Background="{TemplateBinding Background}">
<Border Name="Selection" Visibility="Collapsed" />
<!-- This is used when GridView is put inside the ListView -->
<GridViewRowPresenter Grid.RowSpan="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>


</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="90" DisplayMemberBinding="{Binding Name}"  />
<GridViewColumn Width="90" CellTemplateSelector="{StaticResource customCellTemplateSelector}"  />
</GridView>
</ListView.View>
</ListView>