Pourriez-vous donner un exemple où il est valide d'avoir une ListBox que vous ne pouvez pas sélectionner? Puisque le comportement principal est de sélectionner des éléments. J'aurais probablement choisi une autre façon de l'afficher. (Ce n'est pas moi qui essaie d'être un critique, mais plutôt un réel intérêt pour l'endroit où cela pourrait se produire)
Marthin
3
@Martin: par exemple si vous vouliez faire glisser du contenu à partir d'un élément de liste - dans ce cas, vous n'êtes probablement pas intéressé par la sélection de cet élément. AUSSI: lors du glissement d'un élément: l'élément sélectionné de la zone de liste change pendant que vous faites glisser dans la zone de liste - voir cet article stackoverflow.com/questions/7589142
...
1
Je crois que la raison pour laquelle Shimmy veut utiliser ListBox est que le demandeur peut rendre la listbox sélectionnable à un moment donné. La question me tient également à cœur. Disons que vous construisez un jeu de cartes à jouer. Vous pouvez sélectionner une carte parmi vos cartes, parfois, vous pouvez en sélectionner plusieurs et à d'autres moments, vous ne pouvez en sélectionner aucune.
Gqqnbig
1
De plus, vous avez parfois 10 cartes et seulement 4 d'entre elles sont sélectionnables. Parmi les 4, vous pouvez en sélectionner jusqu'à 3.
Gqqnbig
1
@Marthin: lorsque vous avez un GridView dans une ListBox. Les en-têtes Gridview fournissent de nombreuses fonctionnalités qui ne sont pas disponibles ailleurs. Et vous avez des contrôles d'édition dans les cellules de la grille.
Robin Davies le
Réponses:
264
Approche 1 - ItemsControl
À moins que vous n'ayez besoin d'autres aspects de ListBox, vous pouvez utiliser à la ItemsControlplace. Il place les éléments dans le ItemsPanelet n'a pas le concept de sélection.
<ItemsControlItemsSource="{Binding MyItems}"/>
Par défaut, ItemsControlne 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 .
Approche 2 - Stylisme ListBox
Sinon, stylisez simplement le ListBox de sorte que la sélection ne soit pas visible.
<ListBox.Resources><StyleTargetType="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><SetterProperty="FocusVisualStyle"Value="{x:Null}"/></Style></ListBox.Resources>
non, cela ne changera que l'effet visuel, pas le comportement de sélection réel
Thomas Levesque
8
Ma première suggestion a été d'utiliser ItemsControl. Vous avez manqué ça? :)
Drew Noakes
5
En relisant à nouveau ces commentaires, je tiens à souligner que le commentaire de @Thomas Levesque n'est vrai que pour la deuxième approche que je montre. L'utilisation de plain ItemsControlsupprimera complètement tout concept de sélection.
Drew Noakes le
1
La solution ItemsControl supprime le support de défilement des boîtes (barre de défilement et molette de la souris).
MuiBienCarlota
1
+1 pour l'approche 1 - ItemsControl. Si nous avons une énorme page que nous devons faire défiler, si l'utilisateur passe la souris sur une ListBox, cela désactive effectivement MouseWheel lorsque la listbox saisit les événements MouseWheel. Cela signifie que l'utilisateur est frustré que la molette de souris utilisée pour faire défiler la page entière cesse de fonctionner au hasard, selon que la souris se trouve ou non sur une zone de liste.
Contango
160
J'ai trouvé une solution très simple et directe qui fonctionne pour moi, j'espère que cela le ferait aussi pour vous
C'est parfait. il empêche l'élément sélectionné et d'autres contrôles comme les boutons fonctionnent toujours. exactement ce que je cherchais
Franck
1
+1 pour cette approche. Si nous avons une énorme page que nous devons faire défiler, si l'utilisateur passe la souris sur une ListBox, cela désactive effectivement MouseWheel lorsque la listbox saisit les événements MouseWheel. Cela signifie que l'utilisateur est frustré que la molette de souris utilisée pour faire défiler la page entière cesse de fonctionner au hasard, selon que la souris se trouve ou non sur une zone de liste.
Contango
Excellent. Une approche similaire a également fonctionné pour moi lorsque j'avais besoin de boutons sur des éléments pour ne pas provoquer de sélection d'éléments - mais uniquement si une autre zone de l'élément était cliquée. Réglez simplement les boutons Focusable = "False"!
Jony Adamit
2
Ajoutez cette propriété supplémentaire pour supprimer également la surbrillance au <Setter Property="IsHitTestVisible" Value="False" />
survol de
25
Vous pouvez passer à l'utilisation d'un ItemsControlfichier ListBox. An ItemsControln'a pas de concept de sélection, il n'y a donc rien à désactiver.
Charmant. Je n'ai jamais su que vous pouviez déclarer directement ItemsControl, je pensais que c'était virtuel (MustOverride), merci !!!
Shimmy Weitzhandler le
Mais ItemsControl afficherait-il toujours mes éléments sur une seule ligne?
Chry Cheng
@Chry oui, et en plus, vous pouvez toujours définir manuellement le fichier ItemTemplate.
Shimmy Weitzhandler
2
Cela finit par perdre trop de fonctionnalités - par exemple, le défilement.
Jeff
@Jeff vous pouvez envelopper le ItemsControl dans un ScrollViewer pour obtenir le défilement.
Wilka
12
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.
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.
Simple et fonctionnel, merci! Et cela s'applique également à WP 8.1 Runtime.
Malutek le
8
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:
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:
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.
Dans mon cas, je ne souhaite pas désactiver l'interaction de l'utilisateur avec le contenu de mon ListBoxItemsafin que la solution à définir IsEnabledne fonctionne pas pour moi.
L'autre solution qui tente de remodeler le style ListBoxItemen 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 ItemsControlcassent trop d'autres choses car elles ItemsControlont un aspect complètement différent d'un standard ListBoxet ne prennent pas en charge la virtualisation, ce qui signifie que vous devez de ItemsPaneltoute 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.
@Shimmy: Il est courant que les réponses triviales soient similaires. Il n'y a ici aucune duplication digne de n'importe quel drapeau. Si vous avez d'autres questions à ce sujet, veuillez les poser sur Meta Stack Overflow .
0
Vous pouvez placer un bloc de texte au-dessus de votre zone de liste, cela ne changera pas l'apparence de votre application et ne permettra pas de sélectionner un élément.
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:
Les éléments ListBox Foreground ne deviendront pas gris.
L'arrière-plan de ListBox peut être défini sur Transparent
Très utile pour moi, je voulais grisé et désactivé!
Martin Robins
-3
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.
Réponses:
Approche 1 -
ItemsControl
À moins que vous n'ayez besoin d'autres aspects de
ListBox
, vous pouvez utiliser à laItemsControl
place. Il place les éléments dans leItemsPanel
et n'a pas le concept de sélection.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 leListBox
, ou ajouter la virtualisation à votreItemsControl
.Approche 2 - Stylisme
ListBox
Sinon, stylisez simplement le ListBox de sorte que la sélection ne soit pas visible.
la source
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
la source
Focusable = "False"
!<Setter Property="IsHitTestVisible" Value="False" />
Vous pouvez passer à l'utilisation d'un
ItemsControl
fichierListBox
. AnItemsControl
n'a pas de concept de sélection, il n'y a donc rien à désactiver.la source
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.
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.
la source
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:
la source
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:
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.
la source
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
la source
Je propose encore une autre solution. Re-template simplement
ListBoxItem
pour n'être rien de plus qu'unContentPresenter
, comme ça ...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éfinirIsEnabled
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 ellesItemsControl
ont un aspect complètement différent d'un standardListBox
et ne prennent pas en charge la virtualisation, ce qui signifie que vous devez deItemsPanel
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 leListBox
, 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.la source
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.
Dartrax
la source
Peut-être avez-vous besoin uniquement de la fonctionnalité ItemsControl? Il ne permet pas la sélection:
la source
Vous pouvez placer un bloc de texte au-dessus de votre zone de liste, cela ne changera pas l'apparence de votre application et ne permettra pas de sélectionner un élément.
la source
Une solution simple qui fonctionne sur Windows Phone, par exemple, consiste à définir l'élément sélectionné sur null:
Et dans le code derrière:
la source
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
code
la source
Pour moi, la meilleure solution est:
la source
IsEnabled = false
la source
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.
la source