Dans une application WPF utilisant MVVM, j'ai un contrôle utilisateur avec un élément de liste. Au moment de l'exécution, il utilisera la liaison de données pour remplir la vue de liste avec une collection d'objets.
Quelle est la manière correcte d'attacher un événement de double-clic aux éléments de la vue de liste de sorte que lorsqu'un élément de la vue de liste est double-cliqué, un événement correspondant dans le modèle de vue est déclenché et comporte une référence à l'élément sur lequel l'utilisateur clique?
Comment cela peut-il être fait d'une manière MVVM propre, c'est-à-dire sans code derrière dans la vue?
Je peux faire fonctionner cela avec .NET 4.5. Semble simple et aucun tiers ou code derrière nécessaire.
la source
InputBindings
sont disponibles à partir de .NET 3.0 et ne sont pas disponibles dans Silverlight.J'aime utiliser les comportements et commandes de commande attachés . Marlon Grech a une très bonne implémentation des comportements de commande attachés. En utilisant ceux-ci, nous pourrions alors attribuer un style à la propriété ItemContainerStyle de ListView qui définira la commande pour chaque ListViewItem.
Ici, nous définissons la commande à déclencher sur l'événement MouseDoubleClick, et le CommandParameter, sera l'objet de données sur lequel nous cliquons. Ici, je voyage dans l'arborescence visuelle pour obtenir la commande que j'utilise, mais vous pouvez tout aussi facilement créer des commandes à l'échelle de l'application.
Pour les commandes, vous pouvez soit implémenter directement une ICommand , soit utiliser certains des helpers tels que ceux fournis dans MVVM Toolkit .
la source
acb:
= AttachedCommandBehavior. Le code peut être trouvé dans le premier lien de la réponseJ'ai trouvé un moyen très simple et propre de le faire avec les déclencheurs d'événements du SDK Blend. Clean MVVM, réutilisable et sans code-behind.
Vous avez probablement déjà quelque chose comme ça:
Incluez maintenant un ControlTemplate pour le ListViewItem comme celui-ci si vous n'en utilisez pas déjà un:
Le GridViewRowPresenter sera la racine visuelle de tous les éléments "à l'intérieur" constituant un élément de ligne de liste. Nous pourrions maintenant y insérer un déclencheur pour rechercher les événements routés MouseDoubleClick et appeler une commande via InvokeCommandAction comme ceci:
Si vous avez des éléments visuels "au-dessus" du GridRowPresenter (probablement en commençant par une grille), vous pouvez également y placer le Trigger.
Malheureusement, les événements MouseDoubleClick ne sont pas générés à partir de chaque élément visuel (ils proviennent de Controls, mais pas de FrameworkElements par exemple). Une solution de contournement consiste à dériver une classe de EventTrigger et à rechercher MouseButtonEventArgs avec un ClickCount de 2. Cela filtre efficacement tous les non-MouseButtonEvents et tous les MoseButtonEvents avec un ClickCount! = 2.
Maintenant, nous pouvons écrire ceci ('h' est l'espace de noms de la classe d'assistance ci-dessus):
la source
Je me rends compte que cette discussion date d'un an, mais avec .NET 4, y a-t-il des réflexions sur cette solution? Je suis tout à fait d'accord que le but de MVVM n'est PAS d'éliminer un code derrière un fichier. Je suis également très convaincu que ce n'est pas parce que quelque chose est compliqué que c'est mieux. Voici ce que j'ai mis dans le code derrière:
la source
Vous pouvez utiliser la fonction Action de Caliburn pour mapper des événements à des méthodes sur votre ViewModel. En supposant que vous ayez une
ItemActivated
méthode sur votreViewModel
, le XAML correspondant ressemblerait à ceci:Pour plus de détails, vous pouvez consulter la documentation et les exemples de Caliburn.
la source
Je trouve plus simple de lier la commande lorsque la vue est créée:
Dans mon cas, cela
BindAndShow
ressemble à ceci (updatecontrols + avalondock):Bien que l'approche devrait fonctionner avec la méthode que vous avez pour ouvrir de nouvelles vues.
la source
J'ai vu la solution de rushui avec les InuptBindings, mais je ne pouvais toujours pas atteindre la zone de ListViewItem où il n'y avait pas de texte - même après avoir défini l'arrière-plan sur transparent, je l'ai donc résolu en utilisant différents modèles.
Ce modèle est utilisé lorsque le ListViewItem a été sélectionné et est actif:
Ce modèle est utilisé lorsque le ListViewItem a été sélectionné et est inactif:
Il s'agit du style par défaut utilisé pour ListViewItem:
Ce que je n'aime pas, c'est la répétition du TextBlock et sa liaison de texte, je ne sais pas que je peux me déplacer en déclarant cela dans un seul endroit.
J'espère que ça aidera quelqu'un!
la source
listviewitem
, il ne se soucie probablement pas de savoir s'il est déjà sélectionné ou non. Il est également important de noter que l'effet de surbrillance devra peut-être également être modifié pour correspondre aulistview
style. Voté.J'ai réussi à faire cette fonctionnalité avec le framework .Net 4.7 en utilisant la bibliothèque d'interactivité, tout d'abord assurez-vous de déclarer l'espace de noms dans le fichier XAML
Ensuite, définissez le déclencheur d'événement avec son InvokeCommandAction respectif dans le ListView comme ci-dessous.
Vue:
L'adaptation du code ci-dessus devrait suffire à faire fonctionner l'événement de double-clic sur votre ViewModel, mais je vous ai ajouté la classe Model and View Model de mon exemple afin que vous puissiez avoir une idée complète.
Modèle:
Voir le modèle:
Au cas où vous auriez besoin de l'implémentation de la classe DelegateCommand .
la source
Voici un comportement qui fait cela à la fois sur
ListBox
etListView
.Voici la classe d'extension utilisée pour trouver le parent.
Usage:
la source