一、概述
Messenger中文解释为信使的意思,顾名思义,在MvvmLight中,它的主要作用是用于View和ViewModel、ViewModel和ViewModel之间的通信。
考虑以下场景:
现在有一个主窗体,主窗体上有一个按钮,点击按钮的时候,弹出一个子窗体,用于实时的往主窗体上添加新的项。
这时候Messenger就发挥其强大的威力了。
Messenger类的主要交互模式就是信息的发送和接收(类似消息的发布订阅)。
MVVM Light Messenger 旨在通过简单的设计模式来精简此场景:任何对象都可以是接收端;任何对象都可以是发送端;任何对象都可以是消息。
Messenger的工作流程如下:

二、View和ViewModel之间通信
在View中注册消息 Messenger.Default.Register<string>(this, "ShowSubWindowToken", ShowSubWindow),相当于订阅服务。
消息标志token:ShowSubWindowToken,用于标识只阅读某个或者某些Sender发送的消息,并执行相应的处理,所以Sender那边的token要保持一致
消息处理Action:ShowSubWindow,参数类型为string,用来执行接收到消息后的后续工作。
在ViewModel中发送消息 Messenger.Default.Send("Show subwindow","ShowSubWindowToken"),相当于发布事件。
传递的消息参数为Show subwindow,消息token为ShowSubWindowToken,需要与接收者注册的消息的Token一致。
代码片段如下:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using MvvmLightClosableTabControl.Models;
using System.Collections.ObjectModel;
using System.Windows;
namespace MvvmLightClosableTabControl.ViewModel
{
public class Page3ViewModel:ViewModelBase
{
public Page3ViewModel()
{
Messenger.Default.Register<string>(this, "AddItemToken", AddItem);
}
private ObservableCollection<ListBoxItemModel> listBoxData = new ObservableCollection<ListBoxItemModel>()
{
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/1.png",Info="Honey Peach " },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/2.png",Info="Tomato" },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/3.png",Info="Banana" },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/4.png",Info="Chilli " },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/5.png",Info="Apple" },
};
/// <summary>
/// LisBox数据模板
/// </summary>
public ObservableCollection<ListBoxItemModel> ListBoxData
{
get { return listBoxData; }
set { listBoxData = value; RaisePropertyChanged(() => ListBoxData); }
}
private int selectedIndex = -1;
public int SelectedIndex
{
get { return selectedIndex; }
set
{
selectedIndex = value;
RaisePropertyChanged();
string selValue = $"ImgPath: {listBoxData[selectedIndex].Img}\r\nInfo: {listBoxData[selectedIndex].Info}";
ViewModelLocator.DialogService.ShowInfoDialog($"您当前选择的是:\r\n{selValue}");
}
}
#region Command
private RelayCommand addItemCommand;
public RelayCommand AddItemCommand
{
get
{
if (addItemCommand == null)
{
addItemCommand = new RelayCommand(AddOneItem);
}
return addItemCommand;
}
set { addItemCommand = value; }
}
private void AddOneItem()
{
int a = 3;
Messenger.Default.Send("Show subwindow","ShowSubWindowToken");
}
#endregion
private void AddItem(string msg)
{
ListBoxData.Add(new ListBoxItemModel() { Img = "/MvvmLightClosableTabControl;component/Img/1.png", Info = msg });
MessageBox.Show(msg + " added completed!");
}
}
}
using GalaSoft.MvvmLight.Messaging;
using System.Windows;
using System.Windows.Controls;
namespace MvvmLightClosableTabControl.Pages
{
/// <summary>
/// Interaction logic for Page3.xaml
/// </summary>
public partial class Page3 : Page
{
public Page3()
{
InitializeComponent();
Messenger.Default.Register<string>(this, "ShowSubWindowToken", ShowSubWindow);
}
private void ShowSubWindow(string msg)
{
Page3SubWindow myWindow = new Page3SubWindow()
{
WindowStartupLocation = WindowStartupLocation.CenterOwner, Owner = Application.Current.MainWindow
};
myWindow.ShowDialog();
}
}
}
<Page x:Class="MvvmLightClosableTabControl.Pages.Page3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLightClosableTabControl.Pages"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page3">
<Page.DataContext>
<Binding Path="Page3" Source="{StaticResource Locator}"/>
</Page.DataContext>
<Grid Background="#FFBBB415">
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Content="This is page3." VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40"></Label>
<StackPanel Grid.Row="1" >
<GroupBox Header="Messenger显示子窗口添加用户" FontSize="16" Foreground="DarkGreen">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Button Content="添加条目" Command="{Binding AddItemCommand}"></Button>
<ListBox ItemsSource="{Binding ListBoxData}" DisplayMemberPath="Info" SelectedIndex="{Binding SelectedIndex}">
</ListBox>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</Page>
三、ViewModel和ViewModel之间通信
模拟以下场景:
现在有一个主窗体,主窗体上有一个按钮,点击按钮的时候,弹出一个子窗体,用于实时的往主窗体上添加新的项。
代码片段如下:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using MvvmLightClosableTabControl.Models;
using System.Collections.ObjectModel;
using System.Windows;
namespace MvvmLightClosableTabControl.ViewModel
{
public class Page3ViewModel:ViewModelBase
{
public Page3ViewModel()
{
Messenger.Default.Register<string>(this, "AddItemToken", AddItem);
}
private ObservableCollection<ListBoxItemModel> listBoxData = new ObservableCollection<ListBoxItemModel>()
{
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/1.png",Info="Honey Peach " },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/2.png",Info="Tomato" },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/3.png",Info="Banana" },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/4.png",Info="Chilli " },
new ListBoxItemModel(){ Img="/MvvmLightClosableTabControl;component/Img/5.png",Info="Apple" },
};
/// <summary>
/// LisBox数据模板
/// </summary>
public ObservableCollection<ListBoxItemModel> ListBoxData
{
get { return listBoxData; }
set { listBoxData = value; RaisePropertyChanged(() => ListBoxData); }
}
private int selectedIndex = -1;
public int SelectedIndex
{
get { return selectedIndex; }
set
{
selectedIndex = value;
RaisePropertyChanged();
string selValue = $"ImgPath: {listBoxData[selectedIndex].Img}\r\nInfo: {listBoxData[selectedIndex].Info}";
ViewModelLocator.DialogService.ShowInfoDialog($"您当前选择的是:\r\n{selValue}");
}
}
#region Command
private RelayCommand addItemCommand;
public RelayCommand AddItemCommand
{
get
{
if (addItemCommand == null)
{
addItemCommand = new RelayCommand(AddOneItem);
}
return addItemCommand;
}
set { addItemCommand = value; }
}
private void AddOneItem()
{
int a = 3;
Messenger.Default.Send("Show subwindow","ShowSubWindowToken");
}
#endregion
private void AddItem(string msg)
{
ListBoxData.Add(new ListBoxItemModel() { Img = "/MvvmLightClosableTabControl;component/Img/1.png", Info = msg });
MessageBox.Show(msg + " added completed!");
}
}
}
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
namespace MvvmLightClosableTabControl.ViewModel
{
public class Page3SubWindowViewModel
{
private string itemName = "Orange";
public string ItemName
{
get { return itemName; }
set { itemName = value; }
}
#region Command
private RelayCommand addItemCommand;
public RelayCommand AddItemCommand
{
get
{
if (addItemCommand == null)
{
addItemCommand = new RelayCommand(AddOneItem);
}
return addItemCommand;
}
set { addItemCommand = value; }
}
private void AddOneItem()
{
Messenger.Default.Send(ItemName, "AddItemToken");
}
#endregion
}
}
