Wie deaktiviere ich die Auswahl in einer ListBox?
Wie deaktiviere ich die Auswahl in einer ListBox?
Antworten:
ItemsControl
Sofern Sie keine anderen Aspekte des benötigen ListBox
, können Sie ItemsControl
stattdessen verwenden. Es platziert Elemente in der ItemsPanel
und hat nicht das Konzept der Auswahl.
<ItemsControl ItemsSource="{Binding MyItems}" />
Standardmäßig wird ItemsControl
die Virtualisierung der untergeordneten Elemente nicht unterstützt. Wenn Sie über viele Elemente verfügen, kann die Virtualisierung die Speichernutzung reduzieren und die Leistung verbessern. In diesem Fall können Sie Ansatz 2 verwenden und die Virtualisierung verwendenListBox
oder Virtualisierung zu Ihrer hinzufügenItemsControl
.
ListBox
Alternativ können Sie die ListBox einfach so gestalten, dass die Auswahl nicht sichtbar ist.
<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
wird jedes Auswahlkonzept vollständig entfernt.
Ich habe eine sehr einfache und unkomplizierte Lösung gefunden, die für mich funktioniert. Ich hoffe, sie würde auch für Sie funktionieren
<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" />
Sie können zu a ItemsControl
anstelle von a wechseln ListBox
. An ItemsControl
hat kein Konzept der Auswahl, daher gibt es nichts auszuschalten.
ItemTemplate
.
Eine weitere erwägenswerte Option ist das Deaktivieren der ListBoxItems. Dies kann durch Festlegen des ItemContainerStyle erfolgen, wie im folgenden Snippet gezeigt.
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Wenn der Text nicht grau sein soll, können Sie die deaktivierte Farbe angeben, indem Sie den Ressourcen des Stils mit dem folgenden Schlüssel einen Pinsel hinzufügen: {x: Static SystemColors.GrayTextBrushKey}. Die andere Lösung wäre, die ListBoxItem-Steuerungsvorlage zu überschreiben.
Dies funktioniert auch, wenn ich Listbox anstelle von itemscontrol verwenden muss, aber nur die Elemente anzeige, die nicht auswählbar sein sollten. Ich verwende:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
Ziemlich gute Antworten hier, aber ich suchte nach etwas etwas anderem: Ich möchte eine Auswahl, möchte aber nicht, dass sie angezeigt wird (oder in einer anderen Angelegenheit).
Die oben genannten Lösungen haben bei mir (vollständig) nicht funktioniert, daher habe ich etwas anderes getan: Ich habe einen neuen Stil für meine Listbox verwendet, der die Vorlagen vollständig neu definiert:
<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>
Beginnend damit können Sie ganz einfach Ihre eigene Auswahlmarkierung hinzufügen oder sie so belassen, wenn Sie überhaupt keine möchten.
Während die Antwort von @Drew Noakes in den meisten Fällen eine schnelle Lösung ist, gibt es einen kleinen Fehler beim Einstellen der x: Static-Pinsel.
Wenn Sie die x: Static-Pinsel wie vorgeschlagen festlegen, erben alle untergeordneten Steuerelemente im Listenfeldelement diesen Stil.
Dies bedeutet, dass dies zwar zum Deaktivieren der Hervorhebung des Listenfeldelements funktioniert, jedoch zu unerwünschten Effekten für die untergeordneten Steuerelemente führen kann.
Wenn Sie beispielsweise eine ComboBox in Ihrem ListBoxItem haben, wird die Maus über die Hervorhebung in der ComboBox deaktiviert.
Ziehen Sie stattdessen in Betracht, die VisualStates für die Ereignisse Selected, Unselected und MouseOver festzulegen, wie in der in diesem Stackoverflow-Thread genannten Lösung beschrieben: Entfernen Sie das Steuerelement-Highlight aus ListBoxItem, jedoch nicht untergeordnete Steuerelemente .
-Frinny
Ich schlage noch eine andere Lösung vor. Einfach neu vorlegen ListBoxItem
, um nichts weiter als ein ContentPresenter
, wie so ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Meine Gründe für diesen Ansatz sind folgende:
In meinem Fall möchte ich die Benutzerinteraktion mit den Inhalten von mir nicht deaktivieren, damit die zu setzende ListBoxItems
Lösung IsEnabled
für mich nicht funktioniert.
Die andere Lösung, die versucht, das ListBoxItem
Format durch Überschreiben der farbbezogenen Eigenschaften neu zu gestalten, funktioniert nur in den Fällen, in denen Sie sicher sind, dass die Vorlage diese Eigenschaften verwendet. Das ist in Ordnung für Standardstile, bricht jedoch mit benutzerdefinierten Stilen.
Die Lösungen, die eine ItemsControl
Unterbrechung verwenden, brechen zu viele andere Dinge ab, da ItemsControl
sie ein völlig anderes Aussehen als ein Standard haben ListBox
und keine Virtualisierung unterstützen, was bedeutet, dass Sie die ItemsPanel
ohnehin neu erstellen müssen.
Das oben Gesagte ändert nichts am Standard-Erscheinungsbild von ListBox
, deaktiviert keine Elemente in den Datenvorlagen für ListBox
, unterstützt standardmäßig die Virtualisierung und funktioniert unabhängig von den Stilen, die in Ihrer App verwendet werden oder nicht. Es ist das KISS-Prinzip.
Hinweis: Diese Lösung deaktiviert die Auswahl nicht durch Tastaturnavigation oder Rechtsklick (dh Pfeiltasten gefolgt von Leertaste).
Alle vorherigen Antworten entfernen entweder die Fähigkeitsauswahl vollständig (kein Umschalten in der Laufzeit) oder entfernen einfach den visuellen Effekt, aber nicht die Auswahl.
Was aber, wenn Sie die Auswahl nach Code auswählen und anzeigen möchten, jedoch nicht nach Benutzereingaben? Vielleicht möchten Sie die Auswahl des Benutzers "einfrieren", ohne die gesamte Listbox zu deaktivieren?
Die Lösung besteht darin, die gesamte ItemsContentTemplate in eine Schaltfläche ohne visuelles Chrom zu verpacken. Die Größe der Schaltfläche muss der Größe des Elements entsprechen, damit sie vollständig abgedeckt ist. Verwenden Sie nun die IsEnabled-Eigenschaft der Schaltfläche:
Aktivieren Sie die Schaltfläche, um den Auswahlstatus des Elements "einzufrieren". Dies funktioniert, weil die aktivierte Schaltfläche alle Mausereignisse frisst, bevor sie in den ListboxItem-Eventhandler gelangen. Ihr ItemsDataTemplate erhält weiterhin MouseEvents, da es Teil des Inhalts der Schaltflächen ist.
Deaktivieren Sie die Schaltfläche, um das Ändern der Auswahl durch Klicken zu aktivieren.
<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
Möglicherweise benötigen Sie nur die Funktionalität von ItemsControl? Es erlaubt keine Auswahl:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Eine einfache Lösung, die beispielsweise unter Windows Phone funktioniert, besteht darin, das ausgewählte Element durch Auswahl auf Null zu setzen:
<ListBox SelectionChanged="ListBox_SelectionChanged">
Und im Code dahinter:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
Ich habe einen perfekten Weg gefunden.
Setzen Sie ListBox IsHitTestVisible auf false, damit der Benutzer nicht mit der Maus darüber fahren oder nach unten oder oben scrollen kann.
Capture PreviewGotKeyboardFocus e.Handled = true, damit der Benutzer das Element über die Tastatur auswählen kann. Tab, Pfeil nach oben, Pfeil nach unten.
Dieser Weg Vorteil:
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>
Code
private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
Für mich ist die beste Lösung:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = false
Um eine oder mehrere Optionen in Ihrer Listbox / Dropdown-Liste zu deaktivieren, können Sie das Attribut "deaktiviert" wie unten gezeigt hinzufügen. Dies verhindert, dass der Benutzer diese Option auswählt, und es wird eine graue Überlagerung angezeigt.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);