WPF Liaison d’événements d’interface utilisateur à des commandes dans ViewModel

Je fais un remaniement d’une application simple pour suivre MVVM et ma question est la suivante: comment déplacer un événement SelectionChanged de mon code derrière viewModel? J’ai examiné quelques exemples d’éléments de liaison à des commandes, mais je ne l’ai pas bien compris. Quelqu’un peut-il aider avec cela. Merci!

Quelqu’un peut-il fournir une solution en utilisant le code ci-dessous? Merci beaucoup!

public partial class MyAppView : Window { public MyAppView() { InitializeComponent(); this.DataContext = new MyAppViewModel (); // Insert code required on object creation below this point. } private void contactsList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { //TODO: Add event handler implementation here. //for each selected contact get the labels and put in collection ObservableCollection contactListLabels = new ObservableCollection(); foreach (ContactListModel contactList in contactsList.SelectedItems) { foreach (AggregatedLabelModel aggLabel in contactList.AggLabels) { contactListLabels.Add(aggLabel); } } //aggregate the contactListLabels by name ListCollectionView selectedLabelsView = new ListCollectionView(contactListLabels); selectedLabelsView.GroupDescriptions.Add(new PropertyGroupDescription("Name")); tagsList.ItemsSource = selectedLabelsView.Groups; } } 

Vous devez utiliser un EventTrigger en combinaison avec InvokeCommandAction partir de l’espace de noms Windows.Interactivity. Voici un exemple:

        

Vous pouvez référencer System.Windows.Interactivity en allant dans Add reference > Assemblies > Extensions .

Et l’espace de noms i complet est: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" .

Cette question a un problème similaire.

MVF MVVM: les commandes sont faciles. Comment connecter View et ViewModel avec RoutedEvent

La manière dont je traite ce problème est d’avoir une propriété SelectedItem dans ViewModel, puis de lier le SelectedItem de votre ListBox ou autre pour cette propriété.

Votre meilleur pari est d’utiliser Windows.Interactivity . Utilisez EventTriggers pour attacher une ICommand à un RoutedEvent .

Voici un article pour vous aider à démarrer: Comportements et déclencheurs Silverlight et WPF

Pour réorganiser cela, vous devez changer votre façon de penser. Vous ne serez plus en train de gérer un événement “sélection modifiée”, mais plutôt de stocker l’élément sélectionné dans votre modèle de vue. Vous utiliseriez alors une liaison de données bidirectionnelle afin que, lorsque l’utilisateur sélectionne un élément, votre modèle de vue soit mis à jour et, lorsque vous modifiez l’élément sélectionné, votre vue soit mise à jour.

   

Commander

{eb: EventBinding} (modèle de nommage simple pour rechercher la commande)

{eb: Commande EventBinding = NomCommande}

Paramètre de commande

$ e (EventAgrs)

$ this ou $ this.Property

chaîne

https://github.com/JonghoL/EventBindingMarkup

Je suivrais la première réponse dans cette question

Fondamentalement, votre modèle de vue contiendra une liste de tous vos éléments et une liste des éléments sélectionnés. Vous pouvez ensuite associer un comportement à votre zone de liste qui gère votre liste d’éléments sélectionnés.

Faire cela signifie que vous n’avez rien dans le code derrière et le xaml est assez facile à suivre, aussi le comportement peut être réutilisé ailleurs dans votre application.

  

Parfois, la solution de l’événement de liaison à la commande via le déclencheur d’interactivité ne fonctionne pas, lorsque cela est nécessaire pour lier l’événement du contrôle utilisateur personnalisé. Dans ce cas, vous pouvez utiliser un comportement personnalisé.

Déclarez le comportement de liaison comme:

 public class PageChangedBehavior { #region Attached property public static ICommand PageChangedCommand(DependencyObject obj) { return (ICommand)obj.GetValue(PageChangedCommandProperty); } public static void SetPageChangedCommand(DependencyObject obj, ICommand value) { obj.SetValue(PageChangedCommandProperty, value); } public static readonly DependencyProperty PageChangedCommandProperty = DependencyProperty.RegisterAttached("PageChangedCommand", typeof(ICommand), typeof(PageChangedBehavior), new PropertyMetadata(null, OnPageChanged)); #endregion #region Attached property handler private static void OnPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as PageControl; if (control != null) { if (e.NewValue != null) { control.PageChanged += PageControl_PageChanged; } else { control.PageChanged -= PageControl_PageChanged; } } } static void PageControl_PageChanged(object sender, int page) { ICommand command = PageChangedCommand(sender as DependencyObject); if (command != null) { command.Execute(page); } } #endregion 

}

Et puis le lier à la commande en xaml:

    

Comme le mentionne @Cameron MacFarland, je lierais simplement une propriété à deux sur le viewModel. Dans le setter de propriétés, vous pouvez utiliser la logique de votre choix, telle que l’ajout d’une liste de contacts, en fonction de vos besoins.

Cependant, je n’appellerais pas nécessairement la propriété “SelectedItem”, car viewModel ne devrait pas connaître la couche de vue et son interaction avec ses propriétés. Je l’appellerais quelque chose comme CurrentContact ou quelque chose.

Evidemment, à moins que vous souhaitiez simplement créer des commandes comme exercice pour vous entraîner, etc.