¿Cómo puede saber un ViewModel cuándo se actualizan los datos en un servicio?

StackOverflow https://stackoverflow.com/questions/645557

  •  22-07-2019
  •  | 
  •  

Pregunta

En mi aplicación, tengo varios ViewModels que tienen un solo servicio (repositorio, DAO, lo que sea), llamémoslo WidgetService , inyectado en ellos.

Digamos que uno de estos ViewModels es una lista de todos los widgets de los usuarios. Otro podría ser ViewModel para editar / crear uno solo de estos Widgets.

El usuario puede ver la lista de widgets en el WidgetListView respaldado por un WidgetListViewModel y hacer clic en un botón para agregar un nuevo widget. Para crear este nuevo widget, se crea un CreateWidgetViewModel y se inyecta en el DataContext de algún UserControl / Window, a través de la magia de DataTemplates que muestra el CreateWidgetViewModel en un < strong> CreateWidgetView . Además, la actualización del CreateWidgetViewModel no necesariamente ocurre dentro del alcance del WidgetListViewModel .

Cuando el WidgetListViewModel se inyectó con una instancia del WidgetService . El CreateWidgetViewModel se inyectó con esta misma instancia de WidgetService .

Ahora, cuando el usuario hace clic en guardar en CreateWidgetView se invocará el método Guardar en WidgetService y el widget persistirá. ¡Ahora se debe notificar a WidgetListViewModel que hay un nuevo Widget para mostrar!

La acumulación larga lleva a esta pregunta: ¿Cómo hago para que el WidgetListViewModel sepa que necesita mostrar el nuevo Widget?

He visto un Video en el que Un tipo de Microsoft hace este tipo de cosas usando un evento en el servicio al que se suscribe ViewModel. Sin embargo, la desventaja de esto es que si el servicio sobrevive al modelo de vista, entonces el modelo de vista no tendrá GC'd hasta que el servicio sea GC'd. Podría agregar IDisposable al ViewModel. Pero entonces, ¿cuándo / cómo llamar a Dispose cuando ViewModel solo está representado en la interfaz de usuario a través de DataTemplates?

¿Alguien tiene alguna sugerencia al respecto?

Para aclarar, diría que mi interpretación de MVVM se parece mucho a la de Josh Smith. Al menos en la medida en que mi arquitectura MVVM coincide bastante con la que se encuentra en la fuente Crack.Net.

¿Fue útil?

Solución

Ok, dado que todavía no hay respuestas para esto, pensé en intentarlo, pero no soy un experto en MVVM.

Los eventos parecen ser el camino a seguir con esto. Sin embargo, como señaló, puede haber una pérdida de memoria si el servicio sobrevive al ViewModel. La mejor manera de lidiar con esto es con un oyente de eventos débil.

Eventos débiles le permiten conectarse a un evento con una referencia débil para que si el objeto de origen es GC'd, el controlador de eventos no mantiene viva la fuente.

Otros consejos

Use Prism's ( http://www.codeplex.com/CompositeWPF ) EventAggregator que utiliza el patrón editor-suscriptor, proporcionando un acoplamiento perdido entre los elementos de destino y fuente. Perfecto para exactamente el escenario que describe.

Utilicé el Observer Pattern (también conocido como el patrón de publicación / suscripción) para resolver esto. problema. Hice una clase que llamé EventAggregator que tenía todos los métodos compartidos y miembros de datos. Podría registrarme para un evento en WidgetListViewModel y publicar un " Widget Creado " evento en CreateWidgetViewModel. Puede hacer que WidgetListViewModel implemente IDisposable (mejor) para cancelar el registro de su evento o simplemente puede cancelarlo en el método Finalizar. Funcionó bastante bien y la mejor parte es que los dos modelos de vista no necesitaban tener una idea el uno del otro.

Para algo más complicado o si necesita admitir diferencias de versión entre el servicio y su aplicación, podría implementar un ModelView que manejaría este tipo de cosas haciendo el patrón M-MV-VM-V de sus aplicaciones. Puede parecer un poco exagerado, pero puede hacer que ciertas clases de problemas sean mucho más fáciles de mantener. Sé que he tenido algunos proyectos en los que desearía haber insertado un MV porque la interferencia entre las máquinas virtuales y el código de deshacer se ha vuelto ridícula.

Hay varias opciones:

  1. Use ObservableCollection: esta es probablemente la opción más simple, pero debe tener algún tipo de "maestro" colección en el modelo y que la interfaz de usuario se una directamente a esta colección, esto puede no estar "limpio" Arquitectura MVVM, pero es probablemente la forma más fácil de hacer el trabajo.

  2. Usa el evento y asegúrate de limpiar después de ti mismo, no es fácil de hacer en MVVM.

  3. Use algún intermediario para limpiar automáticamente los eventos (como otros sugirieron) pero no escriba el suyo, hay muchas trampas en esto, WPF tiene una clase incorporada que hace eso, pero olvidé el nombre (si alguien recuerda el nombre, por favor deje un comentario).

  4. Realice actualizaciones periódicas, haga que la clase ViewModel actualice la lista cada X segundos, esta es la única forma de obtener las actualizaciones sin algún tipo de mecanismo de notificación que tenga que administrar.

Estoy de acuerdo con Cameron para usar el patrón WeakEvent. He creado una clase base para ViewModel (en mi ejemplo, uso el nombre PresentationModel) que admite el patrón WeakEvent.

Puede encontrar útil mi proyecto de ejemplo: http://www.codeplex.com/CompositeExtensions

jbe

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top