没有listbox . selectionmode ="None",是否有另一种方法禁用列表框中的选择?

我如何禁用列表框的选择?

97612 次浏览

IsEnabled = false

方法1 - ItemsControl

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

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

默认情况下,ItemsControl不支持其子元素的虚拟化。如果有很多项,虚拟化可以减少内存使用并提高性能,在这种情况下,可以使用方法2并设置ListBox添加虚拟化到你的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>

你可以切换到使用ItemsControl而不是ListBoxItemsControl没有选择的概念,所以没有什么可以关闭。

注意:此解决方案不会禁用通过键盘导航或右键单击进行选择(即。方向键后接空格键)

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

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

解决方案是将整个ItemsContentTemplate包装成一个没有视觉chrome的按钮。按钮的大小必须等于Item的大小,所以它是完全覆盖的。 现在使用按钮的IsEnabled-Property:

启用按钮“冻结”项目的选择状态。这是可行的,因为启用按钮在鼠标事件冒泡到listboxitem - eventandler之前吃掉了所有的鼠标事件。你的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

另一个值得考虑的选项是禁用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控件模板。

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

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

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

我发现了一个非常简单和直接的解决方法,我希望它也适用于你

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

要禁用列表框/下拉菜单中的一个或多个选项,您可以添加“disabled”属性,如下所示。这阻止用户选择这个选项,它得到一个灰色的覆盖。

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

虽然@Drew Noakes的回答是大多数情况下的快速解决方案,但设置x:静态笔刷有一点缺陷。

当您按照建议设置x:Static笔刷时,列表框项中的所有子控件都将继承此样式。

这意味着,虽然这将用于禁用列表框项的高亮显示,但它可能会导致子控件产生不希望看到的效果。

例如,如果你在ListBoxItem中有一个组合框,它将禁用鼠标在组合框中高亮显示。

相反,考虑设置已选、未选和MouseOver事件的VisualStates,就像这个stackoverflow线程:从ListBoxItem中删除控件高亮显示,但不删除子控件中提到的解决方案中所涉及的那样。

-Frinny

一个简单的修复工作在Windows Phone上,例如在选择设置选定项为空:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

在后面的代码中:

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

这也将工作,如果我有需要使用列表框而不是itemscontrol,但只是显示不应该是可选的项目,我使用:

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

这里的答案很好,但我想要一些稍微不同的东西:我想要选择,但只是不希望它被显示(或在不同的事情中显示)。

上面的解决方案对我(完全)不起作用,所以我做了其他的事情:我为我的列表框使用了一种新的样式,它完全重新定义了模板:

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

从那开始,你可以很容易地添加你自己的选择高亮,或者让它像这样,如果你不想要任何。

对我来说,最好的解决办法是:

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

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

这种方式的优点:

  1. 列表框项目前景不会变成灰色。
  2. ListBox背景可以设置为透明

xmal

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

我提出另一种解决办法。简单地将ListBoxItem重新模板化为ContentPresenter,就像这样…

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

我采用这种方法的原因如下:

  1. 在我的例子中,我不想禁用用户与我的ListBoxItems的内容的交互,所以设置IsEnabled的解决方案对我不起作用。

  2. 另一种尝试通过覆盖与颜色相关的属性来重新设置ListBoxItem样式的解决方案仅适用于那些你确定模板使用这些属性的实例。这对于默认样式很好,但对于自定义样式就不行了。

  3. 使用ItemsControl的解决方案破坏了太多其他东西,因为ItemsControl具有与标准ListBox完全不同的外观,并且不支持虚拟化,这意味着无论如何你都必须重新模板ItemsPanel

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

解决方案应该简单直接。

这个方法有几个优点:

  • 键盘导航也被禁用。而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>