Silverlight MVVM advice with 'Composite' Views - silverlight

I have a DomainView that allows you to select an Entity in my domain. The Entity is displayed in an EntityView within the DomainView.
My question is what should the 'DomainViewModel' property be that the EntityView binds to?
The Entity, with the View itself wrapping it up in a EntityViewModel and it binds to that?
The Entity, using a Converter on the binding to convert between the Entity and EntityViewModel?
An EntityViewModel, created by the DomainViewModel?
All would work, I just wondered what would be the 'MVVM-way'? My preference would be for one of the last two.
Lee

With the typical 'MVVM-way', ViewModels shouldn't be aware of other ViewModels and the relationship between View and ViewModel is 1-1.
Sounds like your real question is "How do I communicate data between ViewModels"? A common Master/Details interaction.
Are you using any frameworks? I am personally more familiar with PRISM, but the concepts are similar in MVVM Light and others. In PRISM, a good solution is the EventAggregator. The DomainViewModel publishes an "EntitySelected" aggregate event that is subscribed to by the EntityViewModel.
Another option is to inject a common service (or model, depending on your style) into both ViewModels. That service would provide a public property like CurrentEntity that is set by the DomainViewModel as needed.
Either would provide a mechanism of communicating data between the ViewModels without those ViewModels having any dependency on each other.

Related

Transfer data between two ViewModels

I have two Views and two ViewModels in my WPF app. I am using MVVM ViewModelLocator to transfer data to and fro between my ViewModels. Is this the recommended practice? Is there a better way to achieve this? I am currently using this code to access properties of ViewModel2 in ViewModel1
var _viewmodel2 = (Application.Current.Resources["Locator"] as ViewModelLocator).ViewModel2;
Thanks
What you are after is something like the Event Aggregator pattern. It will use a central 'aggregator' object and subscribing/raising events (with payloads) to ferry data back and forth. Yes, a bit complicated. If your scenario is complex enough for this , here is some more information from a previous SO post here
However......If your scenario is less complicated, you are ok maintaining a reference in viewmodel A to viewmodel B and vice versa. Which seems like it is what you are doing with the ViewModelLocator (which actually uses DI behind the scenes to resolve the instance of ViewModel you are after). This does not violate the MVVM pattern. You just want to be sure to clean up after yourself if during the course of your data share you are subscribing to any events across the viewmodels (same case with event aggregator solution).
If you register your viewmodels in a service locator or IoC container, you can simply fetch the reference from there.
SimpleIoc.Default.GetInstance<MyViewModel>()
Above example uses MvvmLight

MVVM: Decouple Model from ViewModel

I've just started learning WPF MVVM using Prism and Unity.
Decoupling the view from the viewmodel works pretty well, but I don't get how wire up my viewmodel and my model.
I doesn't feel right to just create a new EntityObject right in my viewmodel. I have already skim-read the WAF BookLibrary sample but it is quite bulky and adds a lot of extra stuff around the essential part (binding between view and viewmodel), and the Prism docs don't say a word (as far as I read it) about viewmodel - model interaction.
Does anyone know a good source that explains how to use viewmodel and model in a clean way or can me give some advise?
Best Regards
Jay
Everyone will have their own opinions on this. Personally I don't mind using the model directly in the view model. For me, the whole idea of a view model is to extend your model in such a way that it can be consumed by a view.
A simple example of this would be person object, It would have model properties like like name and age for instance. When I get to the view model stage I may add properties to it like visibility which would not make sense on the model proper.
Another point to note is I would consider a model to be the data and the view model to be the context. So you may have a "Card" View Model for a person but you may also have a "List Item" view model that represents the same model in a different context, with different view model specific properties.
I do tend to make my models up using interfaces where relevant and use Inversion of control to inject them into the view model, that way the only thing my view model actually knows is that it needs an IPerson and that it will be provided in the constructor.
As I said other people will have different ideas, all are correct and its up to you to work out which one suits your needs.

MVVM: does change notification muddy the separation between model and viewmodel?

Let's say I have a model which exposes a collection of objects which I will display and change in a GUI.
So we have Model exposing a collection of ModelItem.
The View binds to a ViewModel which exposes an ObservableCollection of ViewModelItem. ViewModelItem is the Viewmodel of ModelItem
The View contains a ListBox and a DataTemplate. the DataTemplate is for items of type ViewModelItem. The View DataContext points at an instance of ViewModel. The ListBox binds to the ObservableCollection.
I control all the code.
So far so simple. Question:
Is it acceptable to expose the collection on the Model as an ObservableCollection? Further, is it acceptable to implement INotifyPropertyChanged on Model and ModelItem?
My concern is I'm muddying the separation between model and viewmodel, but then common sense says, here's a mechanism for notifying changes to elements in my model, lets use it...
Just wanted to get some perspective from others.
Thanks
Short answer:
YES. Use your notification interfaces on your model when you need to notify of changes. Do not worry about muddying your code with this. Be pragmatic.
Long answer:
My philosophy goes like this: When implementing MVVM, bind directly to model objects when there is nothing extra to do. When you need something new (new behavior, properties the view will utilize, etc) then you wrap the model objects in ViewModel objects. A ViewModel that does nothing but delegate data from the model is nothing but extra code. The moment you need to do something to that data past what the model object gives you, you introduce the layer.
So, to extend my thoughts further on that, (and to answer your question more directly), there needs to be a way for the model to tell the ViewModel when something changes. Often, model data is immutable so it doesn't need this notification mechanism, so it isn't necessary. BUT, it is also often the case that the model DOES change. When that happens, the model has two options: use a custom notification method (events, delegates, etc) or use INotifyPropertyChanged.
If you look at the namespace for INotifyPropertyChanged, it is in System.ComponentModel -- not the view -- so I prefer to use it in the model. It is a well-known interface and you can use it to bind directly to your model from your view. No need to implement anything different.
Taking this philosophy one step further, ObservableCollection is in System.Collections.ObjectModel -- also not view-specific -- and it implements System.Collections.Specialized.INotifyCollectionChanged which also is not view-specific. In other words, ObservableCollection was designed to be a collection that notifies its observers of changes. If you have a model that needs to do that, then ObservableCollection is your tool. It just happens to be convenient (not by accident, though) that WPF and Silverlight use these interfaces for data binding.
I guess this is a long-winded way of saying: "YES. Use your notification interfaces on your model when you need to notify of changes. Do not worry about muddying your code with this. Be pragmatic."
It is definitely acceptable to do both. I would even say it's required to do both. Your common sense abilities work just fine. :)
I would only add that if you don't need all the MVVM functionality for your ModelItems, then you can cut some corners by exposing an ObservableCollection<ModelItem> instead of an ObservableCollection<ViewModelItem>, and modifying your DataTemplate to suit. This will save you quite a bit of "preparation" code, so weigh the pros and cons.
It's certainly acceptable to use change notification in the data model if the data model needs change notification. It's also questionable to use change notification in the data model just because the UI needs change notification.
Generally, I design the data model as if there were no UI, and use the view model as an abstraction layer that hides the data model's implementation details from the UI. On the other hand, in a dynamic application it can be the case that the need for change notification is pervasive enough that it just makes more sense to put it in the data model.
No. It's horrible. Your model should not know how it is used. Giving it this knowledge defeats the object of MVVM.
The model should never know it is being used by WPF, winforms, a dos console, as a service or as a lib. If you tell it this, you are going wrong.
It should also be framework independent, not minding if it's part of MVVM, MVC or MXXX!

Choosing between bound ViewModel properties or messaging to communicate between ViewModel and View using the MVVM Light Toolkit

I'm using MVVM Light toolkit (which I love). I currently have messaging in place for some interaction originating from the ViewModel and intended for consumption by the View. Typically these types of messages indicate the View should do something like hide itself, show a confirmation message that data was saved, etc.
This works. In the constructor for the View, I register with the Messenger:
Messenger.Default.Register<NotificationMessage<PaperNotification>>(this, n => HandlePaperNotification(n));
When I'm using the Messenger to communicate cross-cutting concerns between ViewModels (like identity), I can see that when the ViewModel is cleaned up in the ViewModelLocator, the base class for ViewModels (ViewModelBase) unregisters any subscribed messages. I don't have to do anything, as MVVM Light Toolkit handles that for me. However, when I use them in the Views, I have to expressly unregister them at Closing time, like so:
Messenger.Default.Unregister(this);
I suppose I could implement a base class for Views to inherit from.
However, it strikes me that perhaps this is a code smell to be using the Messenger in the View... it works, but it might not be the best way. I'm wondering if I should instead create a property on the ViewModel and bind whatever part of the View's elements to it. In the example of hiding a form, a property could be a boolean called "Show". As I think about it, I can see that in many cases this will result in having to write a ValueConverter. One way seems less testable. The other way seems to require much more code and perhaps the introduction of excess ValueConverters, which could become a code smell in themselves.
So (after all that build up) my question is this:
Is it preferable to use messages within the View or is it better to add properties (and potentially ValueConverters) to allow the ViewModel to drive it in a more bindable fashion?
In MVVM. ViewModel comunicates with View through DataBinding and Commands. If you need some other functionality, you need to implement it using this means.
Messaging is supposed to be only for ViewModels. Views are supposed to be "stupid" visualisers of your data in ViewModel.
The Messaging logic in MVVM Light is there for communication between ViewModels. I've never run into any communication between View and ViewModel that I couldn't solve with binding and/or commands. Sometimes I need Value Converters and sometimes I need code in the code-behind, but I've never had to make the ViewModel directly push data to the View.
This is an interesting discussion and I found this thread when I was wondering about view model to view communication. Interestingly, MVVMLight's creator seems to find it perfectly acceptable to send messages from a view model to a view. Another example of differing opinions about what is a good MVVM design.

Can a ViewModel talk to View in MVVM pattern?

In MVP pattern, a Presenter has an interface of View so the presenter can call iview.DoSomething().. What about in MVVM pattern?
According to John Gossman's UML diagram http://blogs.msdn.com/johngossman/archive/2006/04/13/576163.aspx , ViewModel doesn't have an interface of View. So, seems like the ViewModel and View should be communicated via Binding only. (or use attached property or blend behavior or etc).
What do you guys think?
I agree with John Gossman. The way the ViewModel "talks" to the View is through Bindings only. In fact - the ViewModel shouldn't care about the View at all. It should simply make data available through properties, and it's up to the View to decide what it will dynamically bind to in the ViewModels. If the ViewModel wants to tell the View something this should occur implicit through Bindings.
A similar question was asked an hour ago - here.
The whole purpose of MVVM is to vastly reduce the amount of code in your code-behind class of your WPF form or user control. The idea is that anything that would be handled by the view in classic MVC/MVP can be translated over to the VM by using a combination of data binding and/or commands. In my general usage of MVVM I have managed to completely remove all of the code-behind in my forms/user controls and the VM has no direct knowledge of the view it is controlling. If you have a situation that really cant be handled by data binding or a command then please elaborate on your initial question and I (or one of the many, many more talented MVVM'ers on here) will try to point you in the right direction.
It typically does - through events on INotifyProperty changed, if nothing else.
Can a ViewModel talk to View in MVVM pattern?
Yes, but in a decoupled way. It’s allowed to introduce an interface IView for the communication.
The MVVM pattern is about to move the logic from the View into the ViewModel. This way we are able to unit test this logic.

Resources