views:

447

answers:

3

MVVM question. Messaging between ViewModel and View, how is it best implemented?

The application has some points of “user communication” such as: “You have entered comments for this selection. Do you wish to save or discard” when the value of a Yes/No/NA selection changes. So I need some proscribed way of the View binding to the ViewModel’s “messages” .

I went down path starting with MVVM Foundation's Messenger. However that is more of a system-wide broadcast then a event/subscriber model. So, if the app has two instances of a View (Person1 EditView and Person2 EditView) open they both get the message when one ViewModel publishes the "do you want to save" message.

What approach have you used?

Thanks Andy

+1  A: 

For all of this you would use binding as your method for "communication". For example, the confirmation message might be shown or hidden based on properties set in your ViewModel.

Here's the View

<Window.Resources>
     <BoolToVisibilityConverter x:key="boolToVis" />
</Window.Resources>
<Grid>

<TextBox Text="{Binding Comment, Mode=TwoWay}" />
<TextBlock Visibility="{Binding IsCommentConfirmationShown, 
                        Converter={StaticResource boolToVis}" 
           Text="Are you sure you want to cancel?" />

<Button Command="CancelCommand" Text="{Binding CancelButtonText}" />
</Grid>

And here is your ViewModel

// for some base ViewModel you've created that implements INotifyPropertyChanged
public MyViewModel : ViewModel 
{
     //All props trigger property changed notification
     //I've ommited the code for doing so for brevity
     public string Comment { ... }
     public string CancelButtonText { ... }
     public bool IsCommentConfirmationShown { ... }
     public RelayCommand CancelCommand { ... }


     public MyViewModel()
     {
          CancelButtonText = "Cancel";
          IsCommentConfirmationShown = false;
          CancelCommand = new RelayCommand(Cancel);
     }

     public void Cancel()
     {
          if(Comment != null && !IsCommentConfirmationShown)
          {
               IsCommentConfirmationShown = true;
               CancelButtonText = "Yes";
          }
          else
          {
               //perform cancel
          }
     }
}

This is not a full sample (the only option is yes! :) ), but hopefully this illustrates that your View and your ViewModel are almost one entity and not two that are making phone calls to each other.

Hope this helps.

Anderson Imes
yes that is the direction I am looking to go. Just may formalize it a bit. thanks
TheZenker
ok... good luck with the formalizing.
Anderson Imes
+1  A: 

What Anderson describes is probably sufficient for the particular requirement you describe. However, you may want to look into Expression Blend Behaviors which provide powerful support for interactions between view models and views, which may be useful in more complex scenarios - using binding for 'messages' will only get you so far.

Note, the expression blend SDK is freely available - you don't have to use Expression Blend to use the SDK or the behavior; although the Blend IDE does have better inbuilt support for 'drag and drop' of behaviors.

Also, note each 'behavior' is a component - in other word it's an extensible model; there are a few built-in behaviors in the SDK, but you can write your own behaviors.

Here are some links. (Note, don't let the 'silverlight' in the URL mislead you - behaviors are supported for both WPF and Silverlight):

information

Blend SDK

video on behaviors

Phil
I have heard about behaviors but not investigated yet. Thanks for the tip, I will check it out.
TheZenker
A: 

A completely alternative approach (no need for Messaging) is shown in the sample applications of

WPF Application Framework (WAF).

jbe