it-swarm.com.de

Es gibt keine ListBox.SelectionMode = "None". Gibt es eine andere Möglichkeit, die Auswahl in einer Listbox zu deaktivieren?

Wie kann ich die Auswahl in einer ListBox deaktivieren?

174
Shimmy

Ansatz 1 - ItemsControl

Wenn Sie keine anderen Aspekte der ListBox benötigen, können Sie stattdessen ItemsControl verwenden. Es platziert Elemente in der Variablen ItemsPanel und hat nicht das Konzept der Auswahl. 

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

Standardmäßig unterstützt ItemsControl keine Virtualisierung der untergeordneten Elemente. Wenn Sie über viele Elemente verfügen, kann die Virtualisierung den Speicherverbrauch reduzieren und die Leistung verbessern. In diesem Fall können Sie Ansatz 2 verwenden und die ListBox formatieren oder Virtualisierung zu Ihrer ItemsControl hinzufügen.

Ansatz 2 - Styling 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>
249
Drew Noakes

Ich habe eine sehr einfache und unkomplizierte Lösung gefunden, die für mich funktioniert

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

Sie können zur Verwendung einer ItemsControl anstelle einer ListBox wechseln. Eine ItemsControl hat kein Auswahlkonzept, es gibt also nichts zu deaktivieren.

24
Wilka

Eine weitere erwägenswerte Option ist das Deaktivieren der ListBoxItems. Dies kann durch Festlegen des ItemContainerStyle wie im folgenden Snippet gemacht erfolgen.

<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-Steuerelementvorlage zu überschreiben.

12
Caleb Vear

Dies funktioniert auch, wenn ich Listbox anstelle von itemscontrol verwenden muss, aber nur die Elemente anzeigt, die nicht auswählbar sein sollen. Ich verwende:

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

Ziemlich gute Antworten, aber ich habe etwas anderes gesucht: Ich möchte eine Auswahl, möchte aber nicht, dass es angezeigt wird (oder in einer anderen Angelegenheit gezeigt wird).

Die oben genannten Lösungen funktionierten nicht (für mich), und ich tat etwas anderes: Ich habe einen neuen Stil für meine Listbox verwendet, der die Vorlagen komplett 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>

Wenn Sie damit beginnen, können Sie ganz einfach Ihre eigene Auswahlmarkierung hinzufügen oder es so belassen, wenn Sie überhaupt keine haben möchten.

2
Andreas Kahler

Während die Antwort von @Drew Noakes eine schnelle Lösung für die meisten Fälle ist, gibt es einen kleinen Fehler, der beim Einstellen der x: Static-Bürsten auftritt.

Wenn Sie die x: Static-Pinsel wie vorgeschlagen festlegen, erben alle untergeordneten Steuerelemente im Listenfeldelement diesen Stil. 

Das bedeutet, dass dies zwar zum Deaktivieren der Hervorhebung des Listenfeldelements führen kann, jedoch zu unerwünschten Auswirkungen für die untergeordneten Steuerelemente führen kann. 

Wenn Sie beispielsweise eine ComboBox in Ihrem ListBoxItem haben, wird die Hervorhebung der Maus in der ComboBox deaktiviert.

Stellen Sie stattdessen fest, dass die VisualStates-Ereignisse für die Selected-, Unselected- und MouseOver-Ereignisse wie in der in diesem Stackoverflow-Thread genannten Lösung beschrieben werden: Entfernen der Steuerelementhervorhebung von ListBoxItem, jedoch nicht der untergeordneten Steuerelemente .

-Frinny

2
Frinavale

Vielleicht benötigen Sie nur die Funktionalität von ItemsControl? Es erlaubt keine Auswahl:

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

Sie können einen Textblock über Ihrer Listbox platzieren. Dadurch wird das Aussehen Ihrer Anwendung nicht geändert. Außerdem können Sie kein Element auswählen.

0
Paras

Hinweis: Diese Lösung deaktiviert nicht die Auswahl durch Tastaturnavigation oder Rechtsklick (dh Pfeiltasten gefolgt von Leertaste).

Alle vorherigen Antworten entfernen entweder die Fähigkeitsauswahl vollständig (kein Wechseln zur Laufzeit) oder entfernen einfach den visuellen Effekt, nicht aber die Auswahl.

Was aber, wenn Sie die Auswahl über einen Code auswählen und anzeigen lassen möchten, jedoch nicht über eine Benutzereingabe? Möglicherweise möchten Sie die Auswahl des Benutzers "einfrieren", ohne die gesamte Listbox zu deaktivieren.

Die Lösung besteht darin, das gesamte ItemsContentTemplate in einen Button zu verpacken, der kein visuelles Chrom besitzt. Die Größe der Schaltfläche muss der Größe des Elements entsprechen, sodass 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, da die aktivierte Schaltfläche alle Mausereignisse frisst, bevor sie zum ListboxItem-Eventhandler übergehen. Ihre ItemsDataTemplate erhält weiterhin MouseEvents, da sie Teil des Schaltflächeninhalts ist.

Deaktivieren Sie die Schaltfläche, um die Auswahl durch Klicken auf zu ändern.

<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

0
dartrax

Ein einfaches Update, das beispielsweise unter Windows Phone funktioniert, ist bei der Auswahl des ausgewählten Elements auf null gesetzt:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

Und im Code dahinter:

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

Ich habe einen perfekten Weg gefunden.
Setzen Sie ListBox IsHitTestVisible auf false, damit der Benutzer den Mauszeiger nicht bewegen oder nach unten scrollen kann.
Capture PreviewGotKeyboardFocus e.Handled = true, damit der Benutzer das Element über die Tastatur auswählen kann, Tab, Pfeil auf, Pfeil ab.

Dieser weg vorteil:

  1. ListBox-Elemente Vordergrund wird nicht grau.
  2. ListBox Background kann auf Transparent gesetzt werden

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

Ich schlage noch eine andere Lösung vor. In meinem Fall möchte ich die Benutzerinteraktion nicht mit dem Inhalt meines ListBoxItems deaktivieren, sodass die Lösung zum Setzen von IsEnabled für mich nicht funktioniert.

Die andere Lösung, die versucht, ListBoxItem durch Überschreiben der farbbezogenen Eigenschaften neu zu gestalten, funktioniert nur für die Fälle, in denen Sie sicher sind, dass die Vorlage diese Eigenschaften verwendet. Das ist gut für Standardstile, bricht aber mit benutzerdefinierten Stile ab.

Die Lösung für die Verwendung eines ItemsControl unterbricht zu viele andere Dinge, da ItemsControl ein völlig anderes Aussehen als ein Standard ListBox hat und keine Virtualisierung unterstützt. Das heißt, Sie müssen das ItemsPanel sowieso neu erstellen.

Meine Lösung ist also, einfach ListBoxItem neu zu erstellen, um nichts anderes als ein ContentPresenter zu sein, wie so ...

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

Das obige Aussehen ändert nicht das Standard-Aussehen von ListBox, deaktiviert Elemente in den Datenvorlagen für ListBox nicht, unterstützt standardmäßig die Virtualisierung und funktioniert unabhängig von den in Ihrer App möglicherweise verwendeten Stilen. Es ist das KISS Prinzip.

0
MarqueIV

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>
0