I currently have a single ViewModel decomposed internally into regions based on areas: ConnectingToFocuserMethods, ConnectingToCameraMethods, etc.
What advantages/disadvantages are there to breaking this apart into multiple view models? I currently have controls which would have a one-to-one mapping to the new view models if I break apart. Would breaking apart be a problem if I find a case where I need to bind to multiple view models from a single control/window/etc.?
Let me do a quick overview the basic MVVM architectural setup first. MVVM is a WPF-centric variation of the MVP pattern (or more specifically, a variation of MVP called Presentation Model). The ViewModel component is often described as a "cross between the View and the Model", but that description isn't really suitable. The ViewModel, in essence, has the same purpose as the Presenter in MVP, which is twofold - (a) abstract away the presentation logic, and (b) implement the application logic - where MVVM's ViewModel emphasizes (a), but note that (b) is not gone.
Now, ViewModel is more accurately described as an abstract representation of a certain kind of a View. As you know, same data can be represented in more than one way (graph, histogram, table, list). Now, don't forget that View is not just a visual representation of the data, but it is, above all, a GUI. This means not only that you can show the data (model, or parts thereof) using one of several possible visual representations, these representations can be implemented in various ways (different UI designs, even different UI libraries), and there usually is certain presentation logic involved (what buttons are enabled when, under what conditions some text will appear in a certain color, what is shown/hidden when an event happens, when to update what UI elements, etc.).
The ViewModel is a representation of a view of a certain general kind (in the same way any other class can be a representation of some other concept); this means that the ViewModel doesn't involve any UI, it doesn't deal with any UI control ("widget") instances - it just has a bunch of variables that represent the state of a view, and a bunch of methods to manipulate this state, and it internally models the presentation logic behavior. That's what the ViewModel is, a conceptual model of a view.
So, Views are just thin, non-"intelligent" renditions of the ViewModel. The View itself does nothing but the most basic View functionality (drawing the controls, raising click events, drawing focus indicator, things like that).
Another aspect of the View-ViewModel interaction is that there must be some way to connect the two, so that changes in one affect the other. The exact way and the route the information travels in order to achieve this synchronicity is a matter of the implementation, but MVVM is designed to take advantage of WPF data binding mechanisms.
Here's the important bit: given all that is said above, it is clear that one ViewModel cannot represent all possible Views. It can represent (1) a family of Views, that share some basic characteristics and have the same (or similar enough) presentation logic, or it can be used to represent those views that (2) conveniently have characteristics and presentation logic that are a subset of the abstract view model.
That probably sounds more confusing than it is; what it really means is that if, for example, a ViewModel represents a view that has some buttons, a list of data entries and a histogram (and the associated presentation logic), it can be connected with (1) any UI implementation that is (at the basic level) organized in the same way, supporting the same stuff (where layout & design, implementation or libraries used can change - but there are always buttons, data list and the histogram), or it can be connected with (2) a view that only has the buttons and the data list, but not a histogram, or maybe a readonly view that only shows the histogram - as long as the presentation model and logic remains suitable.
Also, more than one view can be connected to the same ViewModel, to support multiple simultaneous Views of the same data (different perspectives, etc.), as long as the ViewModel in question can represent those views in a suitable way.
If there's a need for a conceptually different View, then another ViewModel is required. A ViewModel designed to represent, say, a wizard, cannot be hooked up to a View of a drawing application.
It is possible to have one application with more than one view model. At first glance, this might appear to be rather problematic, because the other aspect of the View model, namely, that it is also responsible for the application logic, as well as for the communication with the Model. So, having multiple ViewModels apparently implies a synchronization nightmare.
But, take a note of this: there's no reason for the ViewModel to be represented by a single class. Think about it - the View, for example, is a composite of various instances of several control classes (a form contains buttons, labels, tab panels, which in turn contain other controls). So, the ViewModel itself can also be made of sub-components, and some of them can be shared. In OO, classes can be used to model not just various entities, but also behaviors.
So, you can encapsulate the application logic into a separate class, and an object of this class can be responsible for the business logic and for the ViewModel(s)-Model interaction, and it can be shared by all ViewModels.
In essence, this is the Model View Presenter - View Model architectural style (MVP-VM), which was originally conceived as MVVM for Windows Forms, but there's no reason why it cannot be applied to WPF. For more, see this & this.
This brings me to your final concern, but let me first restate something I said earlier, for easier reference.
[ViewModel] can represent (1) a family of Views, that share some basic characteristics and have the same (or similar enough) presentation logic, or it can be used to represent those views that (2) conveniently have characteristics and presentation logic that are a subset of the abstract view model.
It is possible to bind a single View to multiple ViewModels, but note that this is essentially a special case of (1); the several ViewModels involved together represent a new, composite ViewModel (on a logical level - they don't need to be member fields of a composite ViewModel class).
I hope this makes the options you have more clear.
Now, to wrap it up with a few final words in relation to your questions:
Originally Posted by AlanROrr
What advantages/disadvantages are there to breaking this apart into multiple view models?
As explained above, if you have to support several views which are conceptually significantly different, then you must create more than one ViewModel. The disadvantage in that case might be the fact that keeping everything in sinc becomes more difficult, but this can be mitigated by refining the design, and by factoring out the Presenter in a separate class, sharing it among ViewModels, and letting it handle all the application logic.
Originally Posted by AlanROrr
I currently have controls which would have a one-to-one mapping to the new view models if I break apart. Would breaking apart be a problem if I find a case where I need to bind to multiple view models from a single control/window/etc.?
Normally, simple controls aren't bound to a ViewModel, but rather, there's a more complicated View, with potentially non-trivial presentation logic, that is than bound to a ViewModel, which in turn actually implements the required presentation logic. As for binding to multiple ViewModels: as I said, a set of several ViewModels is a ViewModel itself, it's just made of several components. The concerns here are the following: (1) does the new, composite ViewModel adequately represent the View, and (2) are there any conflicts or costly redundant calls when it comes to application (business) logic, and to interaction with the Model. It requires some work, but these can be designed away.
In response to your last paragraph, (1) yes, the currently single ViewModel adequately represents the View (as well as the multiple tabs/user controls). What I gleaned from your response is this is okay as long as it is not too burdensome (i.e. long, unclear in terms of abstraction/grouping). This is a simple application. (2) No, the redundancy could potentially come in if I added ViewModels for each of the tabs/user controls. I may change to a different construct away from the user controls. Currently, the user controls are changed out within a single View based on the tab that is selected. This approach is very simple without the extra overhead of adding another layer between the View and ViewModel. Getting the information from the Model is okay (i.e. not costly in redundant calls). Again, thank you!
Oh, OK, I see - but what I had in mind with that last paragraph was not about the current state of things, but about what you should consider if you end up with multiple ViewModels (since that was your original question). I was trying to say that multiple ViewModels can be considered to form, together, a new, higher level ViewModel. But then you need to make sure that the presentation logic for the View doesn't imply some interactions among the lower level ViewModels that you didn't predict (in other words if you are going to make the split, think carefully how you're gonna do it, preferably limiting interdependencies of the lower level ViewModels to a minimum).
The other consideration is along the same lines - as you correctly noticed, introducing several ViewModels can in turn introduce redundancies and other problems, so my point was that there can be reduced or avoided by careful design and by extracting all the code that's in charge of the application logic (what the application actually <i>does</i>, regardless of the UI) into a separate Presenter class, that can then be shared among ViewModels, and act as some kind of a hub.
Last edited by TheGreatCthulhu; November 7th, 2012 at 03:16 PM.