WPF ListView关闭选择


119

我有一个简单的WPF 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>

我以前从未在WPF中使用过ListView,但是我敢肯定,如果将IsEnabled属性设置为false,它将禁用整个控件并可能实现您想要的功能,但是我不是100%确定。
James McConnell

嗨,是的,有一个IsEnabled属性,可以禁用整个ListView。我需要ListView才能正常工作,只是不显示选择。
Martin Konicek 2009年

Answers:


135

根据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}" />

2
没有看到相关的部分,但是您可以做同样的事情,在IsMouseOver属性上随意设置背景和边框。
rmoore

88
我现在更好地解决了它-<Setter Property =“ Focusable” Value =“ false” />完全禁止选择该行。
Martin Konicek 2009年

8
嗯,我以为您的意思是在视觉上关闭“选择”。如果您根本不想选择它们,则可以使用ItemsControl来查看(因为如果它们不能集中显示,您仍然可以通过代码设置选择的项),但是您可以使用Grid您将必须执行以下操作:manicprogrammer.com/cs/blogs/…此外,如果您尚未阅读WPF Unleashed一书,那么它可能会对WPF和XAML进行了很好的介绍。
rmoore

2
@MartinKonicek我知道这是一篇旧文章,但您的高评价应为答案;)
WiiMaxx 2013年

1
@MartinKonicek我必须添加,BasedOn="{StaticResource {x:Type ListViewItem}}"因此它不会覆盖其余的网格样式,但我也认为您应该将您的评论作为接受的答案
JumpingJezza 2014年

31

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

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

解释了为什么它不起作用。

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

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

如果列表视图的单元格中包含诸如组合框之类的控件,则将产生不希望的结果,因为它还会更改其颜色。若要解决此问题,您必须重新定义控件的模板。

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

14
这使我在ListView中的所有项目都消失了
Chuck Savage 2012年

18

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

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

4
简单高效。它实际上执行了要求的操作:它关闭了选择,而不仅仅是隐藏选择。这是最好的答案。
Fumidu 2015年

13

这是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触发器和IsSelected / IsSelectionActive MultiTrigger,并且选择时不会有视觉变化。

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


8

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

6

好的,游戏进行得很晚,但是这些解决方案都没有达到我想做的。这些解决方案有两个问题

  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>

5

listview的属性之一是IsHitTestVisible。取消选中它。


简单有效,用ScrollViewer包裹了列表视图也解决了我的问题。
布赖恩·伍

1
我在listview itemtemplate里面有按钮模板。如果取消选择IsHitTestVisible,则无法单击该按钮。就像IsEnabled = false;
Luiey

1

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

  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:

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


1

使用下面的代码:

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

0

下面的代码禁用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> 

0

下面的代码禁用对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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.