Як відключити вибір у 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
. У 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.
Коли ви встановите х: статичні пензлі, як пропонується, усі контрольні елементи дітей у межах списку поля успадкують цей стиль.
Це означає, що, хоча це буде працювати для відключення виділення елемента поля списку, це може спричинити небажані ефекти для дочірнього контролю.
Наприклад, якщо у вас був ComboBox у вашому ListBoxItem, він би відключив мишу над виділенням в ComboBox.
Замість цього, розгляньте можливість встановлення VisualStates для вибраних, невибраних та подій MouseOver, як описано в рішенні, згаданому в цій потоці stackoverflow : Видаліть контрольне виділення з ListBoxItem, але не дочірнє управління .
-Фріні
Я пропоную ще одне рішення. Просто перекройте шаблон, 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.
Примітка. Це рішення не відключає вибір за допомогою навігації на клавіатурі або клацання правою кнопкою миші (тобто клавіші зі стрілками, а потім клавіша пробіл)
Усі попередні відповіді або видаляють можливість вибору повністю (без комутації в режимі виконання), або просто видаляють візуальний ефект, але не виділення.
Але що робити, якщо ви хочете мати можливість вибору та показувати вибір за кодом, а не за допомогою введення користувача? Можливо, ви хочете "заморозити" вибір користувача, не відключивши все Listbox?
Рішення полягає в тому, щоб загортати весь шаблон ItemContentTemplate у кнопку, яка не має візуального хрому. Розмір кнопки повинен дорівнювати розміру Елемента, щоб він повністю покривався. Тепер скористайтеся кнопкою IsEnabled-Properties:
Увімкніть кнопку, щоб "заморозити" стан вибору елемента. Це працює, тому що увімкнена кнопка з'їдає всі події миші, перш ніж вони з'являться до списку ListboxItem-Eventhandler. Ваш ItemDataTemplate як і раніше отримуватиме 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>
дартракс
Можливо, вам потрібна цілком функціональність 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 на хибний, щоб користувач не міг навести мишу або прокрутити вниз або прокрутити вгору.
Capture PreviewGotKeyboardFocus e.Handled = true, щоб користувач міг вибрати предмет за клавіатурою Tab, Arrow up, Arrow down.
Таким чином перевага:
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);