WPF ListView 关闭选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1051215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:38:27  来源:igfitidea点击:

WPF ListView turn off selection

wpflistview

提问by Martin Konicek

I have a simple WPF ListView and a simple question:

我有一个简单的 WPF ListView 和一个简单的问题:

Is it possible to turn off the selection, so when user clicks row, the row is not highlighted?

是否可以关闭选择,因此当用户单击行时,该行不会突出显示?

ListView

列表显示

I would like the row 1 to look just like row 0 when clicked.

我希望第 1 行在单击时看起来像第 0 行。

Possibly related: can I style the look of the hover / selection? Eg. to replace the blue gradient hover look (line 3) with a custom solid color. I have found thisand this, unfortunately not helping.

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

(Achieving the same without using ListView is acceptable too. I'd just like to be able to use logical scrolling and UI virtualization as ListView does)

(在不使用 ListView 的情况下实现相同的效果也是可以接受的。我只是希望能够像 ListView 一样使用逻辑滚动和 UI 虚拟化)

The XAML for ListView is:

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>

回答by rmoore

Per Martin Konicek's comment, to fully disable the selection of the items in the simplest manner:

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

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

However if you still require the functionality of the ListView, like being able to select an item, then you can visually disable the styling of the selected item like so:

但是,如果您仍然需要 ListView 的功能,例如能够选择一个项目,那么您可以在视觉上禁用所选项目的样式,如下所示:

You can do this a number of ways, from changing the ListViewItem's ControlTemplateto just setting a style (much easier). You can create a style for the ListViewItems using the ItemContainerStyleand 'turn off' the background and border brush when it is selected.

您可以通过多种方式执行此操作,从更改 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>

Also, unless you have some other way of notifying the user when the item is selected (or just for testing) you can add a column to represent the value:

此外,除非您有其他方式在项目被选中(或仅用于测试)时通知用户,否则您可以添加一列来表示值:

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

回答by Mark Markindale

Moore's answer doesn't work, and the page here:

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

Specifying the Selection Color, Content Alignment, and Background Color for items in a ListBox

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

explains why it cannot work.

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

If your listview only contains basic text, the simplest way to solve the problem is by using transparent brushes.

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

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

This will produce undesirable results if the listview's cells are holding controls such as comboboxes, since it also changes their color. To solve this problem, you must redefine the control's template.

如果列表视图的单元格持有诸如组合框之类的控件,这将产生不良结果,因为它也会改变它们的颜色。要解决这个问题,您必须重新定义控件的模板。

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

回答by Hayley Guillou

Set the style of each ListViewItem to have Focusable set to false.

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

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

回答by Ben Wilde

Here's the default template for ListViewItem from Blend:

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

Default ListViewItem Template:

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

Just remove the IsSelected Trigger and IsSelected/IsSelectionActive MultiTrigger, by adding the below code to your Style to replace the default template, and there will be no visual change when selected.

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

Solution to turn off the IsSelected property's visual changes:

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

回答by Martin Konicek

The easiest way I found:

我发现的最简单的方法:

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

回答by Reddog

Further to the solution above... I would use a MultiTrigger to allow the MouseOver highlights to continue to work after selection such that your ListViewItem's style will be:

除了上面的解决方案......我将使用 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>

回答by Bradley Burnside

Okay, little late to the game, but none of these solutions quite did what I was trying to do. These solutions have a couple problems

好吧,游戏开始有点晚了,但是这些解决方案都没有完全按照我的意图去做。这些解决方案有几个问题

  1. Disable the ListViewItem, which screws up the styles and disables all the children controls
  2. Remove from the hit-test stack, i.e. children controls never get a mouse-over or click
  3. Make it not focusable, this just plain didn't work for me?
  1. 禁用 ListViewItem,这会弄乱样式并禁用所有子控件
  2. 从命中测试堆栈中删除,即子控件永远不会获得鼠标悬停或点击
  3. 使它不可聚焦,这对我来说根本不起作用?

I wanted a ListView with the grouping headers, and each ListViewItem should just be 'informational' without selection or hover over, but the ListViewItem has a button in it that I want to be click-able and have hover-over.

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

So, really what I want is the ListViewItem to not be a ListViewItem at all, So, I over rode the ListViewItem's ControlTemplate and just made it a simple ContentControl.

所以,我真正想要的是 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>

回答by Jacob Levertov

One of the properties of the listview is IsHitTestVisible. Uncheck it.

列表视图的属性之一是IsHitTestVisible。取消选中它。

回答by BCA

This is for others who may encounter the following requirements:

这适用于可能遇到以下要求的其他人:

  1. Completely replace the visual indication of "selected" (e.g. use some kind of shape), beyond just changing the color of the standard highlight
  2. Include this selected indication in the DataTemplate along with the other visual representations of your model, but,
  3. Don't want to have to add an "IsSelectedItem" property to your model class and be burdened with manually manipulating that property on all model objects.
  4. Require items to be selectable in the ListView
  5. Also would like to replace the visual representation of IsMouseOver
  1. 完全取代“选定”的视觉指示(例如使用某种形状),而不仅仅是改变标准高光的颜色
  2. 将此选定的指示与模型的其他可视化表示一起包含在 DataTemplate 中,但是,
  3. 不想必须将“IsSelectedItem”属性添加到您的模型类,并且不想在所有模型对象上手动操作该属性。
  4. 要求项目在 ListView 中是可选的
  5. 还想替换 IsMouseOver 的可视化表示

If you're like me (using WPF with .NET 4.5) and found that the solutions involving style triggers simply didn't work, here's my solution:

如果您像我一样(在 .NET 4.5 中使用 WPF)并发现涉及样式触发器的解决方案根本不起作用,这是我的解决方案:

Replace the ControlTemplate of the ListViewItem in a style:

用样式替换 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>

..And the DataTemplate:

..和数据模板:

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

Results in this at runtime (item 'B' is selected, item 'D' has mouse over):

在运行时产生这个结果(选择了项目“B”,项目“D”有鼠标悬停):

ListView appearance

列表视图外观

回答by Jorge Freitas

Use the code bellow:

使用以下代码:

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