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 mess开发者_Go百科age when one ViewModel publishes the "do you want to save" message.
What approach have you used?
Thanks Andy
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.
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
精彩评论