Jak mogę wyłączyć zaznaczenie w ListBox?
Jak mogę wyłączyć zaznaczenie w ListBox?
Odpowiedzi:
ItemsControl
O ile nie potrzebujesz innych aspektów ListBox
, możesz ItemsControl
zamiast tego użyć . Umieszcza przedmioty w ItemsPanel
i nie ma pojęcia wyboru.
<ItemsControl ItemsSource="{Binding MyItems}" />
Domyślnie ItemsControl
nie obsługuje wirtualizacji jego elementów potomnych. Jeśli masz wiele elementów, wirtualizacja może zmniejszyć zużycie pamięci i poprawić wydajność, w takim przypadku możesz zastosować podejście 2 i stylizować ListBox
lub dodać wirtualizację do swojegoItemsControl
.
ListBox
Alternatywnie po prostu nadaj stylu ListBox tak, aby zaznaczenie nie było widoczne.
<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
całkowicie usunie każdą koncepcję selekcji.
Znalazłem bardzo proste i proste rozwiązanie, które działa dla mnie, mam nadzieję, że przydałoby się również Tobie
<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" />
Możesz przełączyć się na używanie ItemsControl
zamiast zamiast ListBox
. Nie ItemsControl
ma pojęcia selekcji, więc nie ma się co wyłączać.
ItemTemplate
.
Inną opcją wartą rozważenia jest wyłączenie ListBoxItems. Można to zrobić, ustawiając ItemContainerStyle, jak pokazano w poniższym fragmencie.
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Jeśli nie chcesz, aby tekst był szary, możesz określić wyłączony kolor, dodając pędzel do zasobów stylu za pomocą następującego klucza: {x: Static SystemColors.GrayTextBrushKey}. Innym rozwiązaniem byłoby zastąpienie szablonu kontrolnego ListBoxItem.
To również zadziała, jeśli będę musiał użyć pola listy zamiast kontroli przedmiotów, ale po prostu wyświetlę elementy, których nie można wybrać, używam:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
Dość dobre odpowiedzi tutaj, ale szukałem czegoś nieco innego: chcę selekcji, ale po prostu nie chcę, aby była pokazywana (lub pokazywana w innej sprawie).
Powyższe rozwiązania nie działały dla mnie (całkowicie), więc zrobiłem coś innego: użyłem nowego stylu dla mojego listbox, który całkowicie redefiniuje szablony:
<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>
Zaczynając od tego, możesz łatwo dodać własne zaznaczenie wyboru lub zostawić tak, jeśli w ogóle nie chcesz.
Podczas gdy odpowiedź @Drew Noakes jest szybkim rozwiązaniem w większości przypadków, istnieje pewna wada związana z ustawieniem pędzli x: Static.
Po ustawieniu pędzli x: Static zgodnie z sugestią wszystkie elementy podrzędne w elemencie pola listy odziedziczą ten styl.
Oznacza to, że chociaż będzie to działać w celu wyłączenia podświetlenia elementu listy, może to powodować niepożądane efekty dla elementów podrzędnych.
Na przykład, jeśli masz ComboBox w swoim ListBoxItem, to wyłączy to mysz nad podświetlaniem w ComboBox.
Zamiast tego zastanów się nad ustawieniem VisualStates dla zdarzeń Selected, Unselected i MouseOver zgodnie z rozwiązaniem wymienionym w tym wątku: „ Usuń wyróżnienie kontrolki z ListBoxItem, ale nie kontrolki potomne .
-Frinny
Proponuję jeszcze jedno rozwiązanie. Po prostu ponownie szablon, ListBoxItem
aby był niczym więcej ContentPresenter
, jak ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Moje powody takiego podejścia są następujące:
W moim przypadku nie chcę wyłączać interakcji użytkownika z zawartością mojego, ListBoxItems
więc ustawione rozwiązanie IsEnabled
nie będzie dla mnie działać.
Inne rozwiązanie, które próbuje zmienić styl ListBoxItem
, zastępując właściwości związane z kolorem, działa tylko w tych przypadkach, w których masz pewność, że szablon używa tych właściwości. To jest w porządku dla stylów domyślnych, ale zrywa ze stylami niestandardowymi.
Rozwiązania, które wykorzystują ItemsControl
złamanie zbyt wielu innych rzeczy, ponieważ ItemsControl
mają zupełnie inny wygląd niż standard ListBox
i nie obsługują wirtualizacji, co oznacza, że i tak musisz ponownie utworzyć szablon ItemsPanel
.
Powyższe nie zmienia domyślnego wyglądu ListBox
, nie wyłącza elementów w szablonach danych dla ListBox
, domyślnie obsługuje wirtualizację i działa niezależnie od stylów, które mogą być lub nie być używane w Twojej aplikacji. To zasada KISS.
Uwaga: to rozwiązanie nie wyłącza wyboru poprzez nawigację na klawiaturze lub kliknięcie prawym przyciskiem (tj. Klawisze strzałek, a następnie klawisz spacji)
Wszystkie poprzednie odpowiedzi albo całkowicie usuwają wybór zdolności (bez przełączania w czasie wykonywania), albo po prostu usuwają efekt wizualny, ale nie wybór.
Ale co jeśli chcesz mieć możliwość wyboru i pokazania wyboru według kodu, ale nie na podstawie danych wprowadzonych przez użytkownika? Może chcesz „zamrozić” wybór użytkownika, nie wyłączając całego Listbox?
Rozwiązaniem jest zawinięcie całego ItemsContentTemplate w przycisk, który nie ma wizualnego chromu. Rozmiar przycisku musi być równy rozmiarowi przedmiotu, więc jest całkowicie zakryty. Teraz użyj właściwości IsEnabled przycisku:
Włącz przycisk, aby „zamrozić” stan zaznaczenia elementu. Działa to, ponieważ włączony przycisk zjada wszystkie zdarzenia myszy, zanim zostaną one bąbelkowane do modułu obsługi ListboxItem-Event. Twój ItemsDataTemplate nadal będzie otrzymywać MouseEvents, ponieważ jest częścią zawartości przycisków.
Wyłącz przycisk, aby włączyć zmianę zaznaczenia, klikając.
<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
Może potrzebujesz tylko funkcjonalności ItemsControl? Nie pozwala na wybór:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Prosta poprawka, która działa na przykład na Windows Phone, polega na ustawieniu zaznaczenia wybranego elementu na zero:
<ListBox SelectionChanged="ListBox_SelectionChanged">
A w kodzie za:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
Znalazłem idealny sposób.
Ustaw ListBox IsHitTestVisible na wartość false, aby użytkownik nie mógł najechać myszą, przewinąć w dół ani w górę.
Przechwyć PreviewGotKeyboardFocus e.Handled = true, aby użytkownik mógł wybrać element za pomocą klawiatury, Strzałka w górę, Strzałka w dół.
Zaleta w ten sposób:
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>
kod
private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
Dla mnie najlepszym rozwiązaniem jest:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = false
Aby wyłączyć jedną lub więcej opcji w liście / menu rozwijanym, możesz dodać atrybut „disabled”, jak pokazano poniżej. Zapobiega to wybraniu tej opcji przez użytkownika i uzyskuje szarą nakładkę.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);