example commandmanager .net wpf mvvm binding command

.net - commandmanager - mvvm wpf



WPF MVVM Forma correcta de disparar evento desde ViewModel (1)

En mi aplicación WPF tengo 2 Windows (ambos Windows tienen su propio ViewModel):

  1. Ventana principal de la aplicación que muestra la lista con muchas palabras (vinculada a MainViewModel)

  2. Ventana de diálogo que permite a los usuarios agregar nuevos elementos a la lista (vinculados a AddWordViewModel)

MainViewModel tiene propiedad Articles de List (esta colección está poblada por una de las clases de servicio) vinculada a ListBox de la ventana principal

AddWordViewModel tiene SaveWordCommand que está obligado a Agregar el botón Guardar del diálogo de Word. Su tarea es tomar el texto ingresado por el usuario y pasarlo a la clase de servicio.

Después de que el usuario haga clic en el botón Guardar, debo notificar a MainViewModel para que recargue Artículos del servicio.

Mi idea era exponer el comando público en MainViewModel y ejecutarlo desde AddWordViewModel

¿Cuál es la forma correcta de implementarlo?

¡Gracias!


Los agregadores de eventos son una buena manera de resolver este tipo de problema. Básicamente hay una clase centralizada (por razones de simplicidad, digamos que es un Singleton y enfrenta la posible ira de los tipos anti-singleton) que es responsable de transferir eventos de un objeto a otro. Con sus nombres de clase, el uso puede verse así:

public class MainViewModel { public MainViewModel() { WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>(); event.Subscribe(WordAdded); } protected virtual void WordAdded(object sender WordAddedEventArgs e) { // handle event } } public class AddWordViewModel { //From the command public void ExecuteAddWord(string word) { WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>(); event.Publish(this, new WordAddedEventArgs(word)); } }

La ventaja de este patrón es que puede expandir muy fácilmente su aplicación para tener múltiples formas de crear palabras y múltiples modelos de vista que estén interesados ​​en las palabras que se han agregado y no hay acoplamiento entre los dos para que pueda agregarlos y eliminarlos mientras Necesitar.

Si desea evitar el singleton (y para fines de prueba le sugiero que lo haga), entonces puede valer la pena investigar la inyección de dependencia, aunque ese es realmente otro problema.

De acuerdo, pensamiento final. De volver a leer su pregunta, veo que ya tiene algún tipo de clase de servicio de Word que maneja la recuperación y el almacenamiento de los objetos de Word. No hay ninguna razón para que el servicio no sea responsable de generar el evento cuando se agrega la nueva palabra, ya que ambos ViewModels ya están acoplados. Aunque todavía sugiero que EventAggregator sea más flexible y una solución mejor, pero YAGNI puede aplicar aquí

public class WordService { public event EventHandler<WordAddedEventArgs> WordAdded; public List<string> GetAllWords() { //return words } public void SaveWord(string word) { //Save word if (WordAdded != null) WordAdded(this, new WordAddedEventArgs(word)); //Note that this way you lose the reference to where the word really came from //probably doesn''t matter, but might } } public class MainViewModel { public MainViewModel() { //Add eventhandler to the services WordAdded event } }

Sin embargo, lo que desea evitar es introducir el acoplamiento entre ViewModels que creará al llamar un comando en un ViewModel con el otro, esto limitará severamente sus opciones para expandir la aplicación (¿qué pasaría si un segundo ViewModel se interesara en nuevas palabras? , ¿ahora es responsabilidad de AddWordViewModel decir eso también?)