MVVM Help – Managing Complex Multiple Views

mvvmwpf

I need help creating view models for the following scenario:

  1. Deep, hierarchical data
  2. Multiple views for the same set of data
  3. Each view is a single, dynamically-changing view, based on the active selection
  4. Depending on the value of a property, display different types of tabs in a tab control

enter image description here

My questions:

Should I create a view-model representation for each view (VM1, VM2, etc)?

1. Yes:
    a. Should I model the entire hierarchical relationship? (ie, SubVM1, HouseVM1, RoomVM1)
    b. How do I keep all hierarchies in sync? (e.g, adding/removing nodes)

2. No:
    a. Do I use a huge, single view model that caters for all views?

Here's an example of a single view

Figure 1: Multiple views updated based on active room. Notice Tab control

enter image description here

Figure 2: Different active room. Multiple views updated. Tab control items changed based on object's property.

enter image description here

Figure 3: Different selection type. Entire view changes

enter image description here

Best Answer

To answer the question, Yes, each view should have its own View Model. But there is no need to model the entire hierarchy. Only what the view needs.

The problem I had with most online resources regarding MVVM:

In most examples, the View is almost 1-to-1 mapping of the Model. But in my scenario, where there are different views for different facets of the same Model, I find myself stuck between two choices:

One monolithic view model that is used by all other view models

enter image description here

Or one view model for each view

enter image description here

But both are not ideal.

The Model-oriented View Model (MVM), while low in code duplication, is a nightmare to maintain

The View-oriented View Model (VVM) produces highly-specialised classes for each view, but contains duplicates.

In the end, I decided that having one VM per View is easier to maintain and code for, so I went with the VVM approach.

Once the code is working, I began refactoring all common properties and operations into its current, final form:

enter image description here

In this final form, the common view model class is composed into each VVM.

Of course, I still have to decide what is considered common/specialised. And when a view is added/merged/deleted, this balance changes.

But the nice thing about this is, I am now able to push up/down members from common to VVM and vice versa easily.

And a quick note regarding keeping the objects in-sync:

Having a Common View Model takes care of most of this. Each VVM can simply have a reference to the same Common View Model.

I also tend to start with simple callback methods, and evolving to event/observer if the need for multiple listeners arise.

And for really complex events (ie, unexpected cascading updates), I would switch over to using a Mediator.

I do not shy away from code where a child has a back reference to its parent. Anything to get the code working.

And if the opportunity to refactor arise, I would take it.

The lessons I learnt:

  1. Ugly/Working code > Beautiful/Non-working code
  2. It is easier to merge multiple small classes, than it is to break up a huge class
Related Topic