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


188

Wie deaktiviere ich die Auswahl in einer ListBox?


1
Können Sie ein Beispiel angeben, in dem es gültig ist, eine ListBox zu haben, aus der Sie nicht auswählen können? Da das Hauptverhalten darin besteht, Elemente auszuwählen. Ich würde wahrscheinlich einen anderen Weg wählen, um es anzuzeigen. (Dies ist nicht mein Versuch, ein Kritiker zu sein, sondern ein echtes Interesse daran, wo dies auftreten könnte)
Marthin

3
@Martin: Wenn Sie beispielsweise Inhalte aus einem Listenfeld ziehen möchten, sind Sie in diesem Fall wahrscheinlich nicht daran interessiert, dieses Element auszuwählen. AUCH: beim Ziehen eines Elements: Das ausgewählte Element der Listbox ändert sich, während Sie innerhalb der Listbox ziehen - siehe diesen Beitrag stackoverflow.com/questions/7589142/…
Danield

1
Ich glaube, der Grund, warum Shimmy ListBox verwenden möchte, ist, dass der Fragesteller die Listbox irgendwann auswählbar machen kann. Die Frage ist auch für mich wertvoll. Angenommen, Sie bauen ein Kartenspiel. Sie können eine Karte aus Ihren Karten auswählen, manchmal können Sie mehrere auswählen und manchmal können Sie keine auswählen.
Gqqnbig

1
Außerdem haben Sie manchmal 10 Karten, von denen nur 4 auswählbar sind. Unter den 4 können Sie bis zu 3 auswählen.
Gqqnbig

1
@Marthin: Wenn Sie eine GridView in einer ListBox haben. Gridview-Header bieten viele Funktionen, die anderswo nicht verfügbar sind. Und Sie haben Bearbeitungssteuerelemente in den Zellen der Rasteransicht.
Robin Davies

Antworten:


264

Ansatz 1 - ItemsControl

Sofern Sie keine anderen Aspekte des benötigen ListBox, können Sie ItemsControlstattdessen verwenden. Es platziert Elemente in der ItemsPanelund hat nicht das Konzept der Auswahl.

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

Standardmäßig wird ItemsControldie 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 .

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>

24
Nein, es ändert nur den visuellen Effekt, nicht das tatsächliche Auswahlverhalten
Thomas Levesque

8
Mein erster Vorschlag war, ItemsControl zu verwenden. Hast du das vermisst? :)
Drew Noakes

5
Wenn ich diese Kommentare noch einmal lese, möchte ich darauf hinweisen, dass der Kommentar von @Thomas Levesque nur für den zweiten Ansatz gilt, den ich zeige. Durch die Verwendung von plain ItemsControlwird jedes Auswahlkonzept vollständig entfernt.
Drew Noakes

1
Die ItemsControl-Lösung entfernt die Box-Scrolling-Unterstützung (Bildlaufleiste und Mausrad).
MuiBienCarlota

1
+1 für Ansatz 1 - ItemsControl. Wenn wir eine große Seite haben, auf der wir scrollen müssen, wenn der Benutzer mit der Maus über eine ListBox fährt, wird das Mausrad effektiv deaktiviert, da die Listbox die MouseWheel-Ereignisse erfasst. Dies bedeutet, dass der Benutzer frustriert ist, dass das Mausrad, mit dem die gesamte Seite gescrollt wird, zufällig nicht mehr funktioniert, je nachdem, ob sich die Maus über einer Listbox befindet oder nicht.
Contango

159

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>

Ich denke, er hat es hier ganz gut durchgemacht
Sid

3
Dies ist perfekt. Es verhindert, dass ausgewählte Elemente und andere Steuerelemente wie Schaltflächen weiterhin funktionieren. genau das, wonach ich gesucht habe
Franck

1
+1 für diesen Ansatz. Wenn wir eine große Seite haben, auf der wir scrollen müssen, wenn der Benutzer mit der Maus über eine ListBox fährt, wird das Mausrad effektiv deaktiviert, da die Listbox die MouseWheel-Ereignisse erfasst. Dies bedeutet, dass der Benutzer frustriert ist, dass das Mausrad, mit dem die gesamte Seite gescrollt wird, zufällig nicht mehr funktioniert, je nachdem, ob sich die Maus über einer Listbox befindet oder nicht.
Contango

Ausgezeichnet. Ein ähnlicher Ansatz funktionierte auch für mich, wenn ich Schaltflächen für Elemente benötigte, um keine Elementauswahl zu bewirken - aber nur, wenn auf einen anderen Bereich des Elements geklickt wurde. Einfach die Tasten einstellen Focusable = "False"!
Jony Adamit

1
Fügen Sie diese zusätzliche Eigenschaft hinzu, um auch die Mouseover-Hervorhebung zu entfernen: <Setter Property="IsHitTestVisible" Value="False" />
DonBoitnott

25

Sie können zu a ItemsControlanstelle von a wechseln ListBox. An ItemsControlhat kein Konzept der Auswahl, daher gibt es nichts auszuschalten.


2
Charmant. Ich hätte nie gedacht, dass Sie ItemsControl direkt deklarieren können. Ich dachte, es ist virtuell (MustOverride), danke !!!
Shimmy Weitzhandler

Aber würde ItemsControl meine Artikel trotzdem in einer Zeile rendern?
Chry Cheng

@Chry ja das würde es, und außerdem kannst du das immer manuell einstellen ItemTemplate.
Shimmy Weitzhandler

2
Dies führt dazu, dass zu viele Funktionen verloren gehen - z. B. beim Scrollen.
Jeff

@ Jeff Sie können das ItemsControl in einen ScrollViewer einbinden, um einen Bildlauf zu erhalten.
Wilka

12

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.


Einfach und funktionierend, danke! Und es ist auch auf WP 8.1 Runtime anwendbar.
Malutek

8

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>

3

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.


2

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


2

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:

  1. In meinem Fall möchte ich die Benutzerinteraktion mit den Inhalten von mir nicht deaktivieren, damit die zu setzende ListBoxItemsLösung IsEnabledfür mich nicht funktioniert.

  2. Die andere Lösung, die versucht, das ListBoxItemFormat 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.

  3. Die Lösungen, die eine ItemsControlUnterbrechung verwenden, brechen zu viele andere Dinge ab, da ItemsControlsie ein völlig anderes Aussehen als ein Standard haben ListBoxund keine Virtualisierung unterstützen, was bedeutet, dass Sie die ItemsPanelohnehin 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.


1

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


1

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

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

3
@ Shimmy: Es ist üblich, dass triviale Antworten ähnlich sind. Hier gibt es keine Vervielfältigung, die einer Flagge würdig wäre. Wenn Sie weitere Fragen dazu haben, wenden Sie sich bitte an Meta Stack Overflow .

0

Sie können einen Textblock über Ihrer Listbox platzieren. Dadurch wird das Erscheinungsbild Ihrer Anwendung nicht geändert und es können keine Elemente ausgewählt werden.


1
Sie müssten jedoch weiterhin die Tab-Navigation deaktivieren.
Amanduh

0

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

0

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:

  1. ListBox-Elemente Der Vordergrund wird nicht grau.
  2. ListBox-Hintergrund kann auf Transparent eingestellt 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;
}

-1

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>


-3

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);

Dieses Mal waren Sie hoch und beantworteten eine WPF-Frage mit einer ASP.NET-Lösung.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.