WPF Vinculación de eventos de UI a comandos en ViewModel

Estoy haciendo una refacturación de una aplicación simple para seguir MVVM y mi pregunta es ¿cómo puedo mover un evento SelectionChanged fuera de mi código al viewModel? He visto algunos ejemplos de elementos vinculantes para los comandos pero no los entendí del todo. ¿Alguien puede ayudar con esto? ¡Gracias!

¿Alguien puede proporcionar una solución usando el siguiente código? ¡Muchas gracias!

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

Debería utilizar un EventTrigger en combinación con InvokeCommandAction desde el espacio de nombres de Windows.Interactivity. Aquí hay un ejemplo:

        

Puede hacer referencia a System.Windows.Interactivity yendo Add reference > Assemblies > Extensions .

Y el espacio de nombres i completo es: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" .

Esta pregunta tiene un problema similar.

WPF MVVM: los comandos son fáciles. Cómo conectar View y ViewModel con RoutedEvent

La forma en que trato este problema es tener una propiedad SelectedItem en el ViewModel, y luego vincular el SelectedItem de su ListBox o lo que sea a esa propiedad.

Su mejor apuesta es usar Windows.Interactivity . Use EventTriggers para adjuntar un ICommand a cualquier RoutedEvent .

Aquí hay un artículo para comenzar: Silverlight y WPF Comportamientos y desencadenantes

Para refactorizar esto, necesitas cambiar tu forma de pensar. Ya no se manejará un evento de “selección modificada”, sino que se almacenará el elemento seleccionado en su modelo de vista. Luego, utilizará el enlace de datos bidireccional para que cuando el usuario seleccione un elemento, su modelo de vista se actualice y cuando lo modifique, su vista se actualice.

   

Mando

{eb: EventBinding} (Patrón de nomenclatura simple para encontrar el comando)

{eb: EventBinding Command = CommandName}

CommandParameter

$ e (EventAgrs)

$ this o $ this.Property

cuerda

https://github.com/JonghoL/EventBindingMarkup

Yo seguiría la respuesta principal en esta pregunta

Básicamente, su modelo de vista contendrá una lista de todos sus artículos y una lista de elementos seleccionados. A continuación, puede adjuntar un comportamiento a su listbox que gestiona su lista de elementos seleccionados.

Hacer esto significa que no tiene nada en el código y que el xaml es bastante fácil de seguir, también el comportamiento se puede reutilizar en otra parte de su aplicación.

  

A veces, la solución del evento de vinculación al comando mediante el activador de interactividad no funciona, cuando es necesario para vincular el evento de control de usuario personalizado. En este caso, puede usar un comportamiento personalizado.

Declarar comportamiento vinculante como:

 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 

}

Y luego vincularlo al comando en xaml:

    

Como menciona @Cameron MacFarland, simplemente me vincularía bidireccionalmente a una propiedad en viewModel. En el establecimiento de propiedades puede hacer cualquier lógica que necesite, como agregar a una lista de contactos, según sus requisitos.

Sin embargo, no necesariamente llamaría a la propiedad ‘SelectedItem’ ya que viewModel no debería saber sobre la capa de vista y cómo está interactuando con sus propiedades. Yo lo llamaría algo así como CurrentContact o algo así.

Obviamente esto es a menos que solo desee crear comandos como un ejercicio para practicar, etc.