没有ListBox.SelectionMode =“None”,还有另一种禁用列表框中选择的方法吗?

时间:2009-09-09 09:32:34

标签: .net wpf listbox

如何禁用ListBox中的选择?

16 个答案:

答案 0 :(得分:251)

方法1 - ItemsControl

除非您需要ListBox的其他方面,否则您可以使用ItemsControl。它将项目放在ItemsPanel中,并且没有选择的概念。

<ItemsControl ItemsSource="{Binding MyItems}" />

默认情况下,ItemsControl不支持其子元素的虚拟化。如果您有很多项目,虚拟化可以减少内存使用并提高性能,在这种情况下,您可以使用方法2并设置ListBoxadd virtualisation to your ItemsControl的样式。

方法2 - 样式ListBox

或者,只需设置ListBox的样式,使选择不可见。

<ListBox.Resources>
  <Style TargetType="ListBoxItem">
    <Style.Resources>
      <!-- SelectedItem with focus -->
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
                       Color="Transparent" />
      <!-- SelectedItem without focus -->
      <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
                       Color="Transparent" />
      <!-- SelectedItem text foreground -->
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
                       Color="Black" />
    </Style.Resources>
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
  </Style>
</ListBox.Resources>

答案 1 :(得分:145)

我找到了一个非常简单直接的解决方案,我希望它能为你做到这一点

<ListBox ItemsSource="{Items}">
    <ListBox.ItemContainerStyle>
       <Style TargetType="{x:Type ListBoxItem}">
           <Setter Property="Focusable" Value="False"/>
       </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

答案 2 :(得分:24)

您可以切换为使用ItemsControl代替ListBoxItemsControl没有选择的概念,所以没有什么可以关闭的。

答案 3 :(得分:12)

另一个值得考虑的选择是禁用ListBoxItems。这可以通过设置ItemContainerStyle来完成,如下面的代码片段所示。

<ListBox ItemsSource="{Binding YourCollection}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

如果您不希望文本为灰色,可以通过使用以下键向样式的资源添加画笔来指定禁用的颜色:{x:Static SystemColors.GrayTextBrushKey}。另一种解决方案是覆盖ListBoxItem控件模板。

答案 4 :(得分:7)

这也可以,如果我需要使用listbox而不是itemscontrol,但我只是显示不应该选择的项目,我使用:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="IsHitTestVisible" Value="False" />
    </Style>
</ListBox.ItemContainerStyle>

答案 5 :(得分:2)

虽然@Drew Noakes的答案是大多数情况下的快速解决方案,但设置x:静态画笔会带来一些缺陷。

按照建议设置x:静态画笔时,列表框项目中的所有子控件都将继承此样式。

这意味着,虽然这可用于禁用列表框项的突出显示,但它可能会导致子控件的不良影响。

例如,如果您的ListBoxItem中有一个ComboBox,它会禁用鼠标而不是ComboBox中的突出显示。

相反,请考虑为此stackoverflow线程中提到的解决方案中涵盖的Selected,Unselected和MouseOver事件设置VisualStates:Remove Control Highlight From ListBoxItem but not children controls

-Frinny

答案 6 :(得分:1)

也许你需要ItemsControl的onlly功能?它不允许选择:

<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />

答案 7 :(得分:1)

我提出了另一种解决方案。就我而言,我不想禁用用户与我的ListBoxItems内容的交互,因此设置IsEnabled的解决方案对我不起作用。

另一种尝试通过覆盖与颜色相关的属性来重新设置ListBoxItem样式的解决方案,仅适用于您确定模板使用这些属性的情况。默认样式很好,但会与自定义样式一起破坏。

最后,使用ItemsControl的解决方案会破坏很多其他事情,因为ItemsControl的外观与标准ListBox完全不同,并且不支持虚拟化,这意味着您拥有可以重新模板ItemsPanel

所以我的解决方案只是简单地将ListBoxItem重新模板化为ContentPresenter,就像这样……

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

以上内容不会更改ListBox的默认外观,不会禁用ListBox的数据模板中的项目,默认情况下支持虚拟化,并且可以独立于任何样式或您的应用可能未在使用中。这是KISS的原则。

答案 8 :(得分:0)

注意:此解决方案不会禁用键盘导航选择或右键单击(即箭头键后跟空格键)

之前的所有答案要么删除能力选择完全(在运行时没有切换),要么只是删除视觉效果,而不是选择。

但是,如果您希望能够通过代码选择和显示选择,而不是通过用户输入,该怎么办?您可能想要“冻结”用户的选择而不禁用整个列表框吗?

解决方案是将整个ItemsContentTemplate包装到没有可视铬的Button中。按钮的大小必须等于Item的大小,因此它完全被覆盖。 现在使用按钮的IsEnabled-Property:

启用按钮以“冻结”项目的选择状态。这是因为启用按钮在它们冒泡到ListboxItem-Eventhandler之前会占用所有鼠标事件。您的ItemsDataTemplate仍然会收到MouseEvents,因为它是按钮内容的一部分。

禁用该按钮以启用通过单击更改选择。

<Style x:Key="LedCT" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Button IsEnabled="{Binding IsSelectable, Converter={StaticResource BoolOppositeConverter}}" Template="{DynamicResource InvisibleButton}">
                        <ContentPresenter />
                </Button>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="InvisibleButton" TargetType="{x:Type Button}">
    <ContentPresenter/>
</ControlTemplate>

dartrax

答案 9 :(得分:0)

您可以在列表框上方放置一个Textblock,它不会改变您的应用程序的外观,也不会允许选择任何项目。

答案 10 :(得分:0)

例如,在Windows Phone上运行的简单修复是选择将所选项设置为null:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

在后面的代码中:

    private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        (sender as ListBox).SelectedItem = null;
    }

答案 11 :(得分:0)

对我来说,最好的解决方案是:

        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Focusable" Value="True"/>
                <Setter Property="IsHitTestVisible" Value="False" />
            </Style>
        </ListBox.ItemContainerStyle>

答案 12 :(得分:0)

我找到了一个完美的方式 将ListBox IsHitTestVisible设置为false,以便用户无法鼠标悬停或向下滚动或向上滚动。
捕获PreviewGotKeyboardFocus e.Handled = true,以便用户可以通过键盘选项卡,向上箭头,向下箭头选择项目。

这种优势:

  1. ListBox项目前景不会变为灰色。
  2. ListBox背景可以设置为透明
  3. XmaI位

    <ListBox Name="StudentsListBox" ItemsSource="{Binding Students}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderThickness="0" Background="Transparent" IsHitTestVisible="False" PreviewGotKeyboardFocus="StudentsListBox_PreviewGotKeyboardFocus">
    
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Padding" Value="0"/>
                <Setter Property="Margin" Value="0"/>
    
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Border x:Name="Bd">
                                <ContentPresenter/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="Selector.IsSelectionActive" Value="False" />
                                        <Condition Property="IsSelected" Value="True" />
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Bd" Property="Background" Value="Yellow" />
                                    <Setter TargetName="Bd" Property="BorderBrush" Value="Transparent" />
                                </MultiTrigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>
    
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid Margin="0,0,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Name="GradeBlock" Text="{Binding Grade}" FontSize="12" Margin="0,0,5,0"/>
                    <TextBlock Grid.Column="1" Name="NameTextBlock" Text="{Binding Name}" FontSize="12" TextWrapping="Wrap"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    
    </ListBox>
    

    private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        e.Handled = true;
    }
    

答案 13 :(得分:0)

解决方案应该简单明了。

这个有几个优点:

  • 键盘导航也被禁用。 IsFocusableIsHitTestVisible 等不是这种情况。
  • 没有“禁用”元素的视觉提示:只有 ListBoxItem 被禁用,但是 TextBlock.Foreground 属性设置了正确的颜色。

结果:无法通过键盘或鼠标选择项目,并且颜色不是“灰色”,因为我们没有禁用整个控件。

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Foreground="Black" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

答案 14 :(得分:-3)

IsEnabled = false

答案 15 :(得分:-3)

要禁用列表框/下拉列表中的一个或多个选项,您可以添加“已禁用”属性,如下所示。这样可以防止用户选择此选项,并获得灰色叠加。

ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);