2010-05-13 17 views
12

Estoy construyendo una aplicación que se basa en MVVM-Light. Tengo la necesidad de crear varias instancias de la misma Vista, y cada una debe vincularse a su propio ViewModel.¿Cómo tener múltiples pares "View-ViewModel"?

El valor predeterminado ViewModelLocator implementa ViewModels como singletons, por lo tanto, diferentes instancias de la misma vista se vincularán al mismo modelo de vista.

Pude crear el ViewModel en el VMLocator como un objeto no estático (tan simple como devolver una nueva VM() ...), pero eso solo me ayudaría parcialmente. De hecho, todavía necesito hacer un seguimiento de las ventanas abiertas. Sin embargo, cada ventana podría abrir varias otras ventanas (de un tipo diferente, sin embargo). En esta situación, podría necesitar ejecutar alguna operación en la Vista padre y todos sus elementos secundarios. Por ejemplo, antes de cerrar la Vista P, podría cerrar todos sus elementos secundarios (ver C1, ver C2, etc.).

Por lo tanto, ¿hay alguna manera simple y fácil de lograr esto? ¿O hay alguna mejor práctica que me aconsejarías seguir?

Gracias de antemano por su valiosa ayuda.

Cheers,
Gianluca.

+0

Ok, no estoy seguro de estar en el camino correcto, pero encontré un artículo interesante (por John Papa - http://johnpapa.net/silverlight/simple-viewmodel-locator-for-mvvm-the-patients -have-left-the-asylum /) y estoy tratando de implementar ViewModelLocator de esa manera. Sin embargo, todavía no estoy seguro de cómo proceder para manejar una Vista específica entre las muchas que podría crear ... –

Respuesta

11

No hay obligación de almacenar ViewModels como singletons en ViewModelLocator, pero ciertamente hace que sea más fácil encontrar si la vista también es singleton. Obviamente, si tiene varias instancias de la misma clase de Vista, tendrá múltiples instancias de la misma clase de ViewModel, y ya no podrá ser un singleton.

Para realizar un seguimiento de las múltiples instancias de ViewModel, puede implementar un diccionario en ViewModelLocator que busque un ViewModel según una clave. La clave puede ser una identificación única para la vista, por ejemplo. Una vez que obtenga la vista, recupere su clave y luego recupere el modelo de vista del localizador.

Actualización: A menudo no es necesario rastrear varios modelos de vista. Por ejemplo, puede hacer que la clase Messenger envíe un mensaje a todas las instancias de una clase de viewmodel dada usando la sobrecarga de envío. Entonces, antes de implementar un diccionario para realizar un seguimiento de las máquinas virtuales, pregúntate si realmente lo necesitas. ;)

Espero que ayude, Laurent

+0

Gracias Laurent por su respuesta. De seguro, tendré que cavar esto más profundo. Por cierto, he visto que muchos están utilizando MEF en lugar de un Localizador de ViewModel adecuado ... entonces, estoy experimentando esa solución también. En cuanto al "manejador de ventanas", probé diferentes enfoques pero aún no he encontrado lo mejor para mi caso;) Gracias por toda su ayuda. Gianluca. –

+0

Tengo una aplicación con varios módulos que usan mef, desde un módulo necesito mostrar una vista en otro módulo, la vista de llamada escucha el mensaje de la vista que se muestra en otro módulo, desde la vista se puede crear otra instancia del misma vista, ahora los mensajes comunes se convirtieron en un problema. Dos instancias de la vista envían los mismos mensajes. ¿Cómo puedo resolver esto de manera correcta? ¿Asignar cada instancia de vista e identificar algo? –

+0

@Gianluca: El mejor enfoque en mi experiencia es combinar un ViewModelLocator con MEF o un contenedor IOC (NInject, Unity u otro). – LBugnion

0

que tenía un problema registró y resolvió en this SO question. Resultó estar muy relacionado con la respuesta del Sr. Bugnion aquí (lo que me ayudó enormemente, ¡gracias!)

Lo que encontré es que no es necesario almacenar la propiedad del modelo de visualización en ViewModelLocator en absoluto. Simplemente use ServiceLocator para crear una instancia con una clave, y en su "Servicio de diálogo", pase la clave al ShowDialog<T>(string key = null).

Además, como se ha mencionado en lo que va del hilo, utilice el método Messenger.Default.Send y recuerde llamar viewModel.Cleanup() después para anular el registro de la vista-modelo de Messenger, evitando así Phantom View-modelos de intentar procesar mensajes enviados a todas las instancias de la vista -modelo de clase de modelo.

Cuestiones relacionadas