views:

117

answers:

4

Sometimes a view model needs to raise notifications, that a view should handle and do something in response, esp. when these can't be modeled as properties and property change notifications.

Anything in MVVM Light that can allow the view to listen to events and translate view model notifications into user interface actions via declarative Xaml markup?

+2  A: 

In a "pure" MVVM solution, the only thing that should connect the View to the ViewModel is Bindings. There is nothing stopping you from casting your DataContext to your ViewModel type and hooking an event in the view, but it kind of defeats the purpose of using the MVVM approach. As an alternative, try to rethink of why you think you need to raise an event to the view:

  • Need to display a popup? Some variety of bound list of "popup notifications" can be used, with a proper template, to create popups on the view as the viewmodel "inserts" notification objects into the bound collection.
  • Need to force a drop down open, or some similar UI action? Bind the appropriate property on the UI to a view model property, set the mode to two-way, and set as appropriate on the view model.

etc, etc.

JerKimball
A: 

Hi Vincent,

You are right that sometimes the ViewModel needs to communicate with the View. One way to do this is that the ViewModel raises a CLR event which the View listens to. This can be done in the code-behind of the View.

MVVM is not about eliminating the code-behind of the Views! It’s about separation of concerns and improving the testability with unit tests.

Another way to enable the communication between the ViewModel and the View is by introducing an interface (IView). More information about this approach can be found on the WPF Application Framework (WAF) project site.

jbe
A: 

There is indeed a supported technique in MVVMLight for handling sending Messages from your ViewModel to your View. Look inside the GalaSoft.MvvmLight.Messaging namespace. There is a better way to send dialod messages then the below sample, however this is just a quick example.

Example

ViewModel

public MainPageViewModel()
{
    Messenger.Default.Send("Payment");
}

View

public MainPage()
{
    Messenger.Default.Register<string>(this, DialogRequested);
}

private DialogRequested(string message)
{
    MessageBox.Show(message);
}
Agies
+2  A: 

Personally I find the technique of raising events from the VM and catching them in the view acceptable in certain circumstances. I typically prefer to work with the Messenger for such occasions though, especially if you need custom event args (because it is quite a lot of work to declare a new event args class and a new delegate).

Also, the event handler is a tight coupling between view and viewmodel, while you would typically prefer a loose coupling, but if you are aware of that fact and of the consequences, then why not...

Another technique (for example for navigation, dialogs etc) is to declare an interface with the methods you need (for example IDialogService with AskConfirmation and ShowMessage methods). Then have a class implement that interface (that can be the MainWindow/MainPage itself) and pass it to the ViewModel (for example in the View's constructor right after InitializeComponent was called). In the VM, call these methods when needed. This has the advantage of being quite easy to test (simply mock the IDialogService and check that the methods are called).

I typically move between Messenger and IDialogService depending on various factors. I tend to favor the interface based approach lately though, because it is a little easier to test (but the Messenger is quite testable too so YMMV).

Cheers, Laurent

LBugnion