Many people advice WPF MVVM developers to not expose Model instances from the ViewModel to the View. To display the information from a collection of Model instances, wrap all individual items into ViewModel instances and expose a collection of ViewModels to the View.
However, using MVVM Light it seems to me there are two kinds of ViewModels then:
- ViewModels that have a one-to-one relationship with a view (e.g.
MainWindowViewModel
orCustomerEditorViewModel
). Assumed there is only oneMainWindow
, there will only be oneMainWindowViewModel
. - ViewModels that have a one-to-one relationship with a model instance (e.g.
CustomerViewModel
) and are some kind of "mech suit" for the model instance, providing additional functionality like calculated properties (e.g.Duration
fromStartTime
andEndTime
). A usual company has manyCustomer
s so there will be manyCustomerViewModel
s.
How to wrap Model instances then?
One idea could be to create wrapper classes deriving from ViewModelBase
but not registering and instantiating those with the ViewModelLocator
. I do not think it is a good idea to have two seperate things both called ViewModel.
Another idea could be to use a new base class for the second type of ViewModels, maybe called ModelInfo
. In a single instance of MainViewModel
there would be a collection of CustomerInfo
instances, providing the additional functionality for the Customer
model data.
I would tend to the latter but as this seems to be a pretty general case using MVVM Light, I am sure there must be a common solution to this issue.
Update
I have found an article by Laurent Bugnion, the author of MVVM Light. In his article from the year 2012 Bugnion uses two different approaches of initializing ViewModels:
MainViewModel
is registered with theViewModelLocator
and has no constructor arguments. Thus it is suitable for Dependency Injection and can be instantiated through the ServiceLocator.FriendViewModel
is not registered with theViewModelLocator
and its constructor takes a Model instance as an argument. It can not be instantiated with the ServiceLocator but only by directly calling the constructor and passing the model instance.
This pretty much aligns with the differentiation mentioned in my original question, and with the first idea how to wrap model instances then.