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
Or one view model for each view
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:
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:
- Ugly/Working code > Beautiful/Non-working code
- It is easier to merge multiple small classes, than it is to break up a huge class