Как отключить выбор в ListBox?
Как отключить выбор в ListBox?
Ответы:
ItemsControl
Если вам не нужны другие аспекты ListBox
, вы можете использовать ItemsControl
вместо этого. Он помещает предметы в ItemsPanel
и не имеет понятия выбора.
<ItemsControl ItemsSource="{Binding MyItems}" />
По умолчанию ItemsControl
не поддерживает виртуализацию дочерних элементов. Если у вас много элементов, виртуализация может уменьшить использование памяти и повысить производительность, и в этом случае вы можете использовать подход 2 и стилизовать ListBox
или добавить виртуализацию к вашемуItemsControl
.
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
полностью удалит любую концепцию выбора.
Я нашел очень простое и понятное решение, работающее на меня, надеюсь, оно подойдет и вам
<ListBox ItemsSource="{Items}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Focusable = "False"
!
<Setter Property="IsHitTestVisible" Value="False" />
Вы можете переключиться на использование ItemsControl
вместо ListBox
. У An ItemsControl
нет понятия выбора, поэтому отключать нечего.
ItemTemplate
.
Другой вариант, который стоит рассмотреть, это отключение 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.
Это также будет работать, если у меня есть необходимость использовать listbox вместо 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>
Начиная с этого, вы можете легко добавить собственную подсветку выделения или оставить ее так, если вообще не хотите.
Хотя ответ @Drew Noakes является быстрым решением для большинства случаев, есть некоторая ошибка, возникающая при установке кистей x: Static.
Когда вы устанавливаете кисти x: Static, как предложено, все дочерние элементы управления в элементе списка будут наследовать этот стиль.
Это означает, что, хотя это будет работать для отключения подсветки элемента списка, это может привести к нежелательным эффектам для дочерних элементов управления.
Например, если у вас есть ComboBox в вашем ListBoxItem, он отключил бы выделение мыши внутри ComboBox.
Вместо этого рассмотрите возможность установки VisualStates для событий Selected, Unselected и MouseOver, как описано в решении, упомянутом в этом потоке stackoverflow: Удалить выделение элемента управления из ListBoxItem, но не дочерние элементы управления .
-Frinny
Я предлагаю еще одно решение. Просто повторно шаблон, ListBoxItem
чтобы быть не чем иным ContentPresenter
, как так ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Мои причины такого подхода следующие:
В моем случае я не хочу отключать взаимодействие пользователя с содержимым моего, ListBoxItems
поэтому решение, которое нужно установить IsEnabled
, не будет работать для меня.
Другое решение, которое пытается изменить стиль ListBoxItem
путем переопределения связанных с цветом свойств, работает только для тех случаев, когда вы уверены, что шаблон использует эти свойства. Это хорошо для стилей по умолчанию, но нарушает пользовательские стили.
Решения, которые используют ItemsControl
разрыв, ломают слишком много других вещей, поскольку ItemsControl
выглядят совершенно иначе, чем стандартные, ListBox
и не поддерживают виртуализацию, что означает, что вам ItemsPanel
все равно придется повторно шаблонировать.
Вышеприведенное не меняет внешний вид по умолчанию ListBox
, не отключает элементы в шаблонах данных для ListBox
, поддерживает виртуализацию по умолчанию и работает независимо от стилей, которые могут или не могут использоваться в вашем приложении. Это принцип KISS.
Примечание. Это решение не отключает выбор с помощью навигации по клавиатуре или щелчка правой кнопкой мыши (т. Е. Клавиши со стрелками и пробел)
Все предыдущие ответы либо удаляют возможность выбора полностью (без переключения во время выполнения), либо просто удаляют визуальный эффект, но не выделение.
Но что, если вы хотите иметь возможность выбирать и показывать выбор по коду, а не по пользовательскому вводу? Может быть, вы хотите «заморозить» выбор пользователя, не отключая весь список?
Решение состоит в том, чтобы обернуть весь ItemsContentTemplate в кнопку Button, не имеющую визуального хрома. Размер кнопки должен быть равен размеру Предмета, поэтому он полностью покрыт. Теперь используйте свойство IsEnabled кнопки:
Включите кнопку, чтобы "заморозить" состояние выбора элемента. Это работает, потому что активированная кнопка съедает все события мыши, прежде чем они всплывают в 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
Может быть, вам нужна только функциональность ItemsControl? Не разрешать выбор:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Простое исправление, которое работает, например, в Windows Phone, заключается в том, что для выбранного элемента выбран ноль:
<ListBox SelectionChanged="ListBox_SelectionChanged">
И в коде позади:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
Я нашел идеальный способ.
Установите для ListBox IsHitTestVisible значение false, чтобы пользователь не мог перемещаться, прокручивать вниз или прокручивать вверх.
Capture PreviewGotKeyboardFocus e.Handled = true, чтобы пользователь мог выбрать элемент с помощью клавиш Tab, стрелки вверх, стрелки вниз.
Преимущество этого способа:
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;
}
Для меня лучшим решением является:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = false
Чтобы отключить один или несколько параметров в списке / раскрывающемся списке, вы можете добавить атрибут «отключен», как показано ниже. Это не дает пользователю выбрать эту опцию, и он получает серый наложение.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);