Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concrete examples of state sharing between multiple viewmodels (WPF MVVM)

I have a WPF/Entity Framework (4.0) project with many objects. I'd like to build the application so that that I can have object selection state shared across viewmodels.

For Example: We have Cars, Drivers, Passengers, and Cargo classes. We also have UserControls for CarList, DriverList, etc. and editor windows for CarEditor, DriverEditor, etc. Furthermore, we have viewmodels for all of these (CarListViewModel, DriverListViewModel, CargoEditorViewModel, etc). This all composes a dockable interface where the user can have multiple object lists, editors, and viewers open.

What I want is a concrete code example of how to wireup multiple viewmodels so that selecting a car in the CarList will cause that car to go live in the CarEditorView, but also be selected in any other view for which the context is valid (such as a DriverByCarView- or just DriverList if there is a filter predicate).

There are a number of suggestions and discussions based on this question. The two methods that seem to dominate are:

  • 3018307: Discusses state sharing by mentioning a messaging subsystem
  • 1159035: Discusses state sharing by using an enclosing viewmodel

Is one of these approaches better than the other?

Does anyone have a concrete example of either/both of these methods in the form of a write-up or small code project?

I'm still learning WPF, so pointers to entry points for reading API fundamentals are appreciated, but looking at code examples is where I usually go.

Thanks


In case anyone is interested, here are some other similar discussions:

  • 3816961: Discusses returning multiple viewmodels depending on object type (i.e. a collection of arbitrary types adhering to a specific interface)
  • 1928130: Discusses whether it is a good idea to aggregate viewmodels as properties of other viewmodels (e.g. a MainWindow viewmodel composed of panel viewmodels)
  • 1120061: Essentially discusses whether to have use a viewmodel-per-model strategy or a viewmodel-per-view-element strategy.
  • 4244222: Discusses whether or not to nest the viewmodels when using a nested object hierarchy.
  • 4429708: Discusses sharing collections between viewmodels directly, but doesn't go into detail.
  • List item: Discusses managing multiple selections within a single viewmodel.
like image 620
JohnMetta Avatar asked Jan 05 '11 00:01

JohnMetta


People also ask

Can ViewModels communicate with each other?

One way to have disconnected ViewModels communicate to each other is to use a publish / subscribe mechanism such as PRISMs EventAggregator. However, in a parent / child ViewModel relationship, I think it's fine for the parent to have direct knowledge and control over the child ViewModel.

Can a ViewModel have multiple models?

ViewModel is nothing but a single class that may have multiple models. It contains multiple models as a property. It should not contain any method. In the above example, we have the required View model with two properties.

What is the use of ViewModel in MVVM?

The purpose of ViewModel is to encapsulate the data for a UI controller to let the data survive configuration changes. For information about how to load, persist, and manage data across configuration changes, see Saving UI States.

What is MVVM in WPF How does it work?

MVVM (Model-View-ViewModel) MVVM is a way of creating client applications that leverages core features of the WPF platform, allows for simple unit testing of application functionality, and helps developers and designers work together with less technical difficulties.


1 Answers

A typical way to achieve this is to use a messenger to publish a CarSelected message that details the selected car. Zero or more ViewModels can subscribe to the CarSelected message. ViewModels that are interested in the currently selected car can listen for the message and then act accordingly.

The messenger approach provides a clean decoupled design where publishers and subscribers have no dependencies on each other so can easily evolve independently - they just need to know about the car message. Messengers are an implementation of the mediator pattern.

In Prism the messenger is the EventAggregator and is used for publishing and subscribing to messages.

Update

Apart from the architectural advantages the EventAggregator brings, it also implements weak events to prevent memory leak issues with subscribers that do not explicitly unsubscribe.

Please see the following for EventAggregator documentation:

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

Prism:

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> {} 
like image 62
Tim Lloyd Avatar answered Sep 23 '22 19:09

Tim Lloyd