Comment désactiver la sélection dans une ListBox?
Comment désactiver la sélection dans une ListBox?
Réponses:
ItemsControl
À moins que vous n'ayez besoin d'autres aspects de ListBox
, vous pouvez utiliser à la ItemsControl
place. Il place les éléments dans le ItemsPanel
et n'a pas le concept de sélection.
<ItemsControl ItemsSource="{Binding MyItems}" />
Par défaut, ItemsControl
ne prend pas en charge la virtualisation de ses éléments enfants. Si vous avez beaucoup d'éléments, la virtualisation peut réduire l'utilisation de la mémoire et améliorer les performances, auquel cas vous pouvez utiliser l'approche 2 et styliser le ListBox
, ou ajouter la virtualisation à votreItemsControl
.
ListBox
Sinon, stylisez simplement le ListBox de sorte que la sélection ne soit pas visible.
<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
supprimera complètement tout concept de sélection.
J'ai trouvé une solution très simple et directe qui fonctionne pour moi, j'espère que cela le ferait aussi pour vous
<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" />
Vous pouvez passer à l'utilisation d'un ItemsControl
fichier ListBox
. An ItemsControl
n'a pas de concept de sélection, il n'y a donc rien à désactiver.
ItemTemplate
.
Une autre option à considérer est la désactivation de ListBoxItems. Cela peut être fait en définissant ItemContainerStyle comme indiqué dans l'extrait de code suivant.
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Si vous ne voulez pas que le texte soit gris, vous pouvez spécifier la couleur désactivée en ajoutant un pinceau aux ressources du style avec la clé suivante: {x: Static SystemColors.GrayTextBrushKey}. L'autre solution serait de remplacer le modèle de contrôle ListBoxItem.
Cela fonctionnera également, si j'ai besoin d'utiliser listbox au lieu de itemscontrol, mais que j'affiche simplement les éléments qui ne devraient pas être sélectionnables, j'utilise:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
Assez bonnes réponses ici, mais je cherchais quelque chose de légèrement différent: je veux une sélection, mais je ne veux pas qu'elle soit montrée (ou montrée dans un autre sujet).
Les solutions ci-dessus n'ont pas fonctionné pour moi (complètement), j'ai donc fait autre chose: j'ai utilisé un nouveau style pour ma listbox, qui redéfinit complètement les modèles:
<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>
En commençant par cela, vous pouvez facilement ajouter votre propre mise en surbrillance de sélection, ou la laisser comme ça si vous n'en voulez pas du tout.
Bien que la réponse de @Drew Noakes soit une solution rapide dans la plupart des cas, il existe un petit défaut lié au réglage des brosses x: Static.
Lorsque vous définissez les pinceaux x: Static comme suggéré, tous les contrôles enfants de l'élément de zone de liste héritent de ce style.
Cela signifie que, bien que cela fonctionnera pour désactiver la mise en évidence de l'élément de zone de liste, cela peut entraîner des effets indésirables pour les contrôles enfants.
Par exemple, si vous aviez un ComboBox dans votre ListBoxItem, cela désactiverait la souris sur la mise en évidence dans le ComboBox.
Au lieu de cela, envisagez de définir les VisualStates pour les événements Selected, Unselected et MouseOver comme indiqué dans la solution mentionnée dans ce thread stackoverflow: Supprimez la surbrillance du contrôle de ListBoxItem mais pas les contrôles enfants .
-Frinny
Je propose encore une autre solution. Re-template simplement ListBoxItem
pour n'être rien de plus qu'un ContentPresenter
, comme ça ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Mes raisons de cette approche sont les suivantes:
Dans mon cas, je ne souhaite pas désactiver l'interaction de l'utilisateur avec le contenu de mon ListBoxItems
afin que la solution à définir IsEnabled
ne fonctionne pas pour moi.
L'autre solution qui tente de remodeler le style ListBoxItem
en remplaçant les propriétés liées à la couleur ne fonctionne que pour les instances où vous êtes sûr que le modèle utilise ces propriétés. C'est bien pour les styles par défaut, mais rompt avec les styles personnalisés.
Les solutions qui utilisent un ItemsControl
cassent trop d'autres choses car elles ItemsControl
ont un aspect complètement différent d'un standard ListBox
et ne prennent pas en charge la virtualisation, ce qui signifie que vous devez de ItemsPanel
toute façon remodeler.
Ce qui précède ne modifie pas l'apparence par défaut du ListBox
, ne désactive pas les éléments dans les modèles de données pour le ListBox
, prend en charge la virtualisation par défaut et fonctionne indépendamment de tout style utilisé ou non dans votre application. C'est le principe KISS.
Remarque: cette solution ne désactive pas la sélection par navigation au clavier ou clic droit (c.-à-d. Touches fléchées suivies d'une touche d'espace)
Toutes les réponses précédentes suppriment complètement la sélection de capacité (pas de changement à l'exécution) ou suppriment simplement l'effet visuel, mais pas la sélection.
Mais que faire si vous voulez pouvoir sélectionner et afficher la sélection par code, mais pas par entrée utilisateur? Peut-être voulez-vous "figer" la sélection de l'utilisateur sans désactiver toute la Listbox?
La solution consiste à encapsuler l'ensemble ItemsContentTemplate dans un Button qui n'a pas de chrome visuel. La taille du bouton doit être égale à la taille de l'élément, il est donc complètement couvert. Utilisez maintenant la propriété IsEnabled du bouton:
Activez le bouton pour "figer" l'état de sélection de l'élément. Cela fonctionne car le bouton activé mange tous les événements de la souris avant qu'ils ne remontent au ListboxItem-Eventhandler. Votre ItemsDataTemplate recevra toujours MouseEvents car il fait partie du contenu des boutons.
Désactivez le bouton pour activer la modification de la sélection en cliquant sur.
<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
Peut-être avez-vous besoin uniquement de la fonctionnalité ItemsControl? Il ne permet pas la sélection:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Une solution simple qui fonctionne sur Windows Phone, par exemple, consiste à définir l'élément sélectionné sur null:
<ListBox SelectionChanged="ListBox_SelectionChanged">
Et dans le code derrière:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
J'ai trouvé un moyen parfait.
Définissez ListBox IsHitTestVisible sur false afin que l'utilisateur ne puisse pas survoler la souris, faire défiler vers le bas ou faire défiler vers le haut.
Capture PreviewGotKeyboardFocus e.Handled = true afin que l'utilisateur puisse sélectionner l'élément à l'aide du clavier Tab, Flèche vers le haut, Flèche vers le bas.
De cette façon, l'avantage:
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;
}
Pour moi, la meilleure solution est:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = false
Pour désactiver une ou plusieurs options dans votre zone de liste / liste déroulante, vous pouvez ajouter l'attribut «désactivé» comme indiqué ci-dessous. Cela empêche l'utilisateur de sélectionner cette option, et il obtient une superposition grise.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);