使用Messenger类
this.Frame.Navigate(typeof(BlankPage2));
Messenger.Default.Send<object>("dfsdfd");
Messenger.Default.Register<string>(this,
m => {
if (m!=null)
{
DialogResult = m.ToString();
}
}
);
额,继续写点东西吧,弄个比较实在点的实例出来,这个实例非常的简单,就是页面通过点击一个按钮,弹出一个ChildWindow 来进行选择某条记录,然后将在Page中获取ChildWindow中选择的记录。
假设调用ChildWindow的页面(page)为 Parent,对应的VM ParentViewModel
被调用的ChildWindow 的页面为 (childwindow)Child 对应的VM ChildViewModel
既然用MVVM模式,那么在ChildWindow中也要使用MVVM模式,now begin
实现思路如下:
1 在Parent的OnNavigatedTo中注册消息,在该消息的会调函数中打开Child
// parent.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Messenger.Default.Register<NotificationMessage>(this, "OpenChildWindow", OpenChildWindow);
}
// 回调
private void OpenChildWindow(NotificationMessage childWindowName)
{
string strChildWindowName = childWindowName.Notification;
switch (strChildWindowName)
{
case "Child":
ChildWindows. Child child = new ChildWindows. Child ();
child.Show();
break;
}
}
你可能会问,为什么要在.cs 中写代码呢,为什么不在VM的构造函数中写呢,其实是有原因的,我们想想VM的好处之一就是可以将View 和 业务逻辑彻底的分开,例如以后想要将silverlight项目修改成WPF的项目,我们只需要简单的将WPF的View绑定一下就OK了,但是VM不是万能的,我们在silverlight项目中独有的一些东西怎么能够替换到WPF中呢,例如ChildWindow,如果我们见ChildWindow的打开事件写到的ViewModel中,那么以后移植就会有花费更多的额外劳动,所以就将ChildWindow 的打开写在了Parent.cs中,也许你会问,那么直接在Button的Click事件中写不就完事了吗,其实也未必不可,但是以后的附加工作也会很多,你从Child中选择的记录怎样提交到ParentViewModel中?别忘了,我们应用的还是MVVM模式。
2 既然是选择某条记录,那么就可以这样的往下推,既然是要选择记录,那么在ChildViewModel 中就要有一个备选的集合属性 ,怎样获取的我就不管了,如:
Private ObservableCollection<User> _userInfos;
public ObservableCollection<User> UserInfos
{
get
{
return _userInfos;
}
set
{
if (_userInfos== value)
{
return;
}
_userInfos = value;
RaisePropertyChanged(“UserInfos”);
}
}
既然有集合,那么就要有选择项的
Public User UserInfoSelect // 属性传递
额,childwindow 中好像准备的差不多了
那么在ParentViewMode中该做些什么呢?当然,首先得有个接收选中的记录的属性吧,和ChildViewModel 中的相同。
Public User UserInfoSelect // 属性接收
额,那么他们怎样的进行传递呢?消息啊,这时候消息派上用场了,在ParentViewModel的构造中,我们注册一个消息。
Messenger.Default.Register<GenericMessage<UserInfo>>(this, "GetUserInfo", GetUserInfo);
// 回调
Private void GetUserInfo(GenericMessage<UserInfo> userInfo)
{
if (userInfo.Content != null)
this.UserInfoSelect = userInfo.Content;
}
在接下来就是一个连线的过程了,首先我们在ParentViewModel的 弹出选择窗体的事件中通知消消息OpenChildWindow à消息接收到之后调用回调函数弹出Childà在ChildViewModel中获取选择的记录给UserInfoSelectà通知消息GetUserInfo,并且传递UserInfoSelectàParentViewModel获取消息,调用回调方法,获取Child中选择的记录。Ok,工作以完成。
那么接下来就要说一些注意的事情了,既然有注册了消息,还有回调函数,就会出现多次被执行的情况(多次注册一个消息而没有注销),那么我们就要记住一定要在适当的位置注销消息,例如在Child的Closing事件中注销事件,或者在Page的OnNavigatedFrom(NavigationEventArgs e)中写注销消息。
注销消息如下:
Messenger.Default.Unregister<GenericMessage<UserInfo>>( "GetUserInfo");
其实为什么不在ViewModel 中弹出窗体,其实还有一个原因,就是如果我们要在ViewModel中弹出窗体,那么我们就要知道UI中的Child,这也就是说ViewModel要引用UI,这样做就有些…