WPF MVVM: How do ViewModels communicate with each other? - wpf

I have a View which has 2 sub views on it and a ViewModel is assigned to each view:
ViewA - ViewModelA
{
ViewB - ViewModelB
ViewC - ViewModelC
}
ViewB has a text box and ViewC has a combobox, both of which i need access from ViewModelA. Not the GUI control itself, but the bound value i.e. .Text of the textbox and .SelectedItem of the ComboBox. Currently i just have ViewModelB and ViewModelC as properties on ViewModelA but it feels wrong.
What's the standard way for view models to communicate with each other without breaking the MVVM pattern?

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.
Personally, I don't think composing a ViewModel out of other ViewModels is a bad practice. I do it all the time. I generally favor composition over inheritance in my ViewModels.

The ViewModels usually 'inherit' relationships from the Model. And it's not wrong to add a relation when it makes sense.
It's perfectly OK for a ViewModel to have a property referring to another ViewModel.

Related

View Updating Model directly In WPF MVVM instead of ViewModel

This is the link i am following for learning MVVM in WPF and i have a question:-
https://www.tutorialspoint.com/mvvm/mvvm_first_application.htm
DataContext of the WPF window is set to a VIEWMODEL object.
Itemsource of a List-DataTemplate is set to a List from the same VIEWMODEL Object.
The Model contains an implementation of INotifyPropertyChanged.
When i update the view,the INotifyPropertyChanged of MODEL gets fired ie VIEW is directly updating the MODEL while what i have understood till now is that VIEW interacts with the VIEWMODEL only via Bindings and Commands and never with the MODEL DIRECTLY.It is always the ViewModel which interacts with the Model to fetch data for the View.But here,the View is updating the Model DIRECTLY.This is confusing me owing to my limited knowledge.
Please guide.
If the view model exposes the model through a property, the view may actually bind directly to the model through this property. This doesn't really violate the MVVM pattern and is perfectly fine, especially if the model class implements the INotifyPropertyChanged interface. If it does, you can say that the model is kind of a (child) view model.
A "real" model such as a domain object or a service shouldn't have any knowledge about WPF and how you raise change notifications to a view. Therefore it rarely makes sense to bind directly to such objects but if your models are "WPF aware" and implements view related interfaces, you can bind to them without any issues.
It is a common error to bind the Model thru lists to the View. The correct approach would be always to create a ViewModel of that Model (the list element) and bind to it.
For example:
Otherwise you are opening the door to including data on ModelB that should be stored in the ViewModelB.

MVVM: Loosely coupling of ViewModels

I have classes, A, B, C, D
A has a reference to E and B and to a list of C and D.
In AViewModel these are exposed in a tree.
The View for A looks like as in the picture.
When a node selected a correspondent view should be displayed.
There is ViewModels for E,B,C and D
My question is the following:
For example E is the selected node. I store it in AViewModel as "object SelectedItem".
What is the best way to create an EViewModel in a loosely coupled way, so that I do not want to reference EViewModel in AViewModel.
Update:
I was thinking about one solution, but I never seen that in other places:
For example I could expose only my POCOs (B, C, D, E) from AViewModel. And in XAML I could bind the ContentControl directly to these objects. With a converter I could have a BViewModel when I bind to B and so on.
A common and widely accepted way to communicate between view models and other components in a loosely coupled way in an MVVM application would be to use an event aggregator or a messenger. Please refer to the following links for more information.
Using the event aggregator pattern to communicate between view models: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/
MVVM - Messenger and View Services in MVVM: https://msdn.microsoft.com/en-us/magazine/jj694937.aspx.
Another option would be to use a shared service that you inject the view models with: https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf
Using an event aggregator, messenger or shared service means that you can remove all references between the view model classes.
Instead of the view model classes having strong references to each other back and forth, each view model only knows about a single event aggregator/messenger/shared service and communicates only with this one. View model A may send any number of messages that any other view models may subscribe to listen to and handle internally.
My question is about best practices on topic of creating an instance of a ViewModel without having a tight coupling, not about the communication between loosely coupled ViewModels
Creating an instance of another view model without creating a string coupling is impossible. If one view model creates an instance of another view model they are by definition strongly coupled. To prevent this you could inject a view model with an interface type that the other view model implements, e.g.:
public ViewModelB(IViewModelA viewModelA)
{
//...
}
Then ViewModelB is dependant on an interface type instead of a concrete implementation of the ViewModelA. It's a bit better than doing something like this because then ViewModelA and ViewModelB will always be - as mentioned above - strongly coupled to each other:
public ViewModelB()
{
_viewModelA = new ViewModellA();
}
But if you really care about loose coupling between your view model classes, you should get rid of the direct references and start to use an event aggregator or a messenger to communcate between them.
If your A View displays the "list", plus the selected view, it's perfectly acceptable to have EViewModel reference in AViewModel. ViewModels may be the "reflection" of the views. So if the A view will contain an EView, AViewModel may contain an EViewModel. You just nest your view models so it creates the same tree as in the view layer.
On top of that, what I would do is not reference E or B,... in AViewModel, but reference only EViewModel, BViewModel,... So AView list does not display model classes but ViewModel classes. Your SelectedItem gets typed as a ViewModel and you can directly bind your "Display" view part to the SelectedItem. Then you can use the right DataTemplate on the view layer to display the according view. Hope it helps

Correct MVVM design patterns - ViewModel and DataContext

I started playing around with Windows Phone development. I am using MVVM ligth and I am trying to follow good practices. But lately I ran into an issue:
Is it okay to use ViewModel inside a ViewModel as a property?
My scenario is that I am having a MainViewModel which is a Panorama object. This Panorama objects consists of few PanaoramaItems (Notes, Calender and About Controls/Pages).
My question is, if I have for the MainPage.xaml a MainViewModel, is it okay if I put the other ViewModels as properties (NotesViewModel, CalenderViewModel, AboutViewModel) to the MainViewModel, in that case those will inherit from the MainPage the DataContext and I would just bind to a property of the MainViewModel. Or should I rather use the locator pattern to allow the other pages/control to get their own ViewModels and do not inherit the DataContext?
Is it okay, if a control has a ViewModel or should it be rather for pages?
If the Parent and Child ViewModels are related: sure, that is fine, it does not violate the pattern.
This setup allows you to re-use ViewModels and Views across pages and controls.

Composite WPF: Data Template vs. View Model Injection

Here is the simple question: what do you use to link your views to your view models?
Basically there is 2 common ways of achieving that, data templates and view model injection (samples below).
What I would like to know is why do you prefer a method over the other and in which case you use them. Precise the MVVM framework you use.
The data template way or "View Model first" approach (Resources.xaml):
<DataTemplate DataType="{x:Type my:PersonViewModel}">
<my:PersonView/>
</DataTemplate>
The view model injection way or "View first" approach (PersonView.xaml.cs):
[Import]
public PersonViewModel ViewModel
{
set
{
this.DataContext = value;
}
}
I prefer using DataTemplates
It allows me to set multiple Views for the same ViewModel based on a property
My ViewModels are my application, and the View is nothing more than a pretty layer that makes my ViewModel's User-Friendly. If I use ViewModel injection, than the Views become my application and the development team suddenly has to worry about the UI side of things
My ViewModels are managed by other ViewModels. For example, one ViewModel might contain a collection of other ViewModels that get displayed in a TabControl. Adding or Closing tabs is done within the parent ViewModel. This sort of thing is not easily accomplished with the View controlling the application state.
I can initialize different ViewModels using parameterized constructors based on my needs instead of having to use generic Import ones
That's just a few reasons... I'm sure there's others but they don't come to mind right now
We use a view model first approach because we find it easier to manage, particular on larger scale enterprise apps. We use Caliburn.Micro to take care of view location and binding.
I use both. DataTemplates for small projects, but for larger or team projects we use view model injection.

Should my ViewModel have an ObservableCollection of Views or ViewModels?

I'm trying to understand the basic MVVM design approach when using ItemsControl by binding it via DataTemplates to ObservableCollections on the ViewModel.
I've seen examples that bind to ObservableCollections of strings, Views, and ViewModels.
Binding to strings seems to be only for demos, it is the binding to "ViewModels that contain collections of Views that contain collections of ViewModels" that the power of WPF seems to really come out.
For those of use proficient in the MVVM pattern, what is your standard approach to binding ItemsControl, ListView, ListBox to collections in a ViewModel? I'm looking for advice from experience like this:
always use ObservableCollection<...> and never List<...> because...
something better than ItemsControl to display a collection is...
in order to get filtering to work in your ViewModel instead of code-behind, use...
use collections of Views when ... and collections of ViewModels when...
90% of the time I create an ItemsControl and bind it to an ObservableCollection of Views which have their own ViewModels...
I would use an ObservableCollection of ViewModels for the following reasons:
ObservableCollection already has events available for signaling when it has been modified (e.g. when items are added/removed from the collection).
We're at the ViewModel 'layer' so it provides cleaner separation to have a ViewModel contain a collection of ViewModels rather than Views
If it is necessary to modify or get data from items within the collection you can more easily modify/access that data if the items are ViewModels (if they're views you'll frequently be casting the View's DataContext or accessing its UI elements).
I like using an ObservableCollection of ViewModels. The view that binds to the collection can define a DataTemplate that gives the ViewModel its look. This leads to less coupling among the components.
I have the same question, but replace the "view" with "model". :)
I have a MODEL with a collection of other models.
I want my viewmodel to have an observable collection of other viewmodels, but once I instantiate it like that - the connection between the model collection content is lost.
Do I now need to start wiring all the events from the viewmodels observable collection back to the models collection?

Resources