Ejemplos concretos de estado compartido entre varios viewmodel (WPF, MVVM)


Tengo un proyecto WPF/Entity Framework (4.0) con muchos objetos. Me gustaría construir la aplicación para que pueda tener el estado de selección de objetos compartido a través de viewmodels.

Por ejemplo: Tenemos Automóviles, Conductores, Pasajeros y clases de Carga. También tenemos controles de usuario para CarList, DriverList, etc. y editor de ventanas para CarEditor, DriverEditor, etc. Además, tenemos viewmodels para todos ellos (CarListViewModel, DriverListViewModel, CargoEditorViewModel, etc). Todo esto compone una interfaz acoplable donde el usuario puede tener varias listas de objetos, editores y visores abiertos.

Lo que quiero es un ejemplo de código concreto de cómo wireup múltiples viewmodels para que la selección de un coche en el CarList hará que ese coche para ir en vivo en el CarEditorView, pero también ser seleccionado en cualquier otra vista para la que el contexto es válido (como un DriverByCarView - o simplemente DriverList si hay un predicado de filtro).

Hay una serie de sugerencias y discusiones basado en esta pregunta. Los dos métodos que parecen dominar son:

  • 3018307: Discute el intercambio de estados mencionando un subsistema de mensajería
  • 1159035: Analiza el intercambio de estados mediante el uso de un viewmodel adjunto

¿Es mejor uno de estos enfoques que el otro?

¿Alguien tiene un ejemplo concreto de uno o ambos de estos métodos en forma de escritura o proyecto de código pequeño?

Todavía estoy aprender WPF, por lo que los punteros a los puntos de entrada para leer los fundamentos de la API son apreciados,pero mirar ejemplos de código es donde suelo ir.

Gracias


En caso de que alguien esté interesado, aquí hay algunas otras discusiones similares:

  • 3816961: Discute devolver varios modelos de vista dependiendo del tipo de objeto (es decir, una colección de tipos arbitrarios que se adhieren a una interfaz específica)
  • 1928130: Discute si es una buena idea agregar viewmodels como propiedades de otros viewmodels (por ejemplo, un MainWindow viewmodel compuesto de panel viewmodels)
  • 1120061: Esencialmente discute si usar una estrategia viewmodel-per-model o una estrategia viewmodel-per-view-element.
  • 4244222: Analiza si anidar o no los viewmodels cuando se utiliza una jerarquía de objetos anidados.
  • 4429708: Discute el intercambio de colecciones entre viewmodels directamente, pero no entra en detalle.
  • Elemento de lista: Trata sobre la administración de varias selecciones dentro de un solo viewmodel.
Author: Community, 2011-01-05

1 answers

Una forma típica de lograr esto es usar un messenger para publicar un mensaje CarSelected que detalla el coche seleccionado. Cero o más ViewModels pueden suscribirse al mensaje CarSelected. ViewModels que están interesados en el coche seleccionado actualmente puede escuchar el mensaje y luego actuar en consecuencia.

El enfoque de messenger proporciona un diseño desacoplado limpio donde los editores y los suscriptores no tienen dependencias entre sí, por lo que pueden evolucionar fácilmente de forma independiente, solo necesitan saber sobre el mensaje del coche. Los mensajeros son una implementación del patrón del mediador.

En Prism el mensajero es el EventAggregator y se utiliza para publicar y suscribirse a mensajes.

Update

Aparte de las ventajas arquitectónicas que trae EventAggregator, también implementa eventos débiles para evitar problemas de pérdida de memoria con los suscriptores que no cancelan explícitamente la suscripción.

Por favor vea lo siguiente para EventAggregator documentación:

Http://msdn.microsoft.com/en-us/library/ff649187.aspx

Prisma:

Http://compositewpf.codeplex.com /

Prism Example

public class ViewModel1
{
    private readonly IEventAggregator _eventService;
    private Car _selectedCar;

    public ViewModel1(IEventAggregator eventService)
    {
        _eventService = eventService;
    }

    //Databound property...
    public Car SelectedCar
    {
        set
        {
            _selectedCar = value;

            var msg = new CarSelectedMessage { Car = _selectedCar };

            _eventService.GetEvent<CarSelectedEvent>().Publish(msg);
        }
    }
}

public class ViewModel2
{
    public ViewModel2(IEventAggregator eventService)
    {
        eventService.GetEvent<CarSelectedEvent>().Subscribe(msg =>
        {
            //DoStuff with msg...
        });
    }
}

public class Car {}

public class CarMessage
{
    public Car Car { get; set; }
}

public class CarSelectedEvent : CompositePresentationEvent<CarMessage> {}
 12
Author: Tim Lloyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 04:26:48