加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

MVVMLight 子窗体传递数据

(2011-10-19 19:39:51)
标签:

mvvm

light

传递参数

子窗体

父窗体

传值

消息

杂谈

分类: .net4.0

,继续写点东西吧,弄个比较实在点的实例出来,这个实例非常的简单,就是页面通过点击一个按钮,弹出一个ChildWindow 来进行选择某条记录,然后将在Page中获取ChildWindow中选择的记录。

 

假设调用ChildWindow的页面(page) Parent,对应的VM  ParentViewModel

被调用的ChildWindow 的页面为 (childwindow)Child 对应的VM ChildViewModel

既然用MVVM模式,那么在ChildWindow中也要使用MVVM模式,now begin

 

实现思路如下:

 

1 ParentOnNavigatedTo中注册消息,在该消息的会调函数中打开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的项目,我们只需要简单的将WPFView绑定一下就OK了,但是VM不是万能的,我们在silverlight项目中独有的一些东西怎么能够替换到WPF中呢,例如ChildWindow,如果我们见ChildWindow的打开事件写到的ViewModel中,那么以后移植就会有花费更多的额外劳动,所以就将ChildWindow 的打开写在了Parent.cs中,也许你会问,那么直接在ButtonClick事件中写不就完事了吗,其实也未必不可,但是以后的附加工作也会很多,你从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,工作以完成。

 

那么接下来就要说一些注意的事情了,既然有注册了消息,还有回调函数,就会出现多次被执行的情况(多次注册一个消息而没有注销),那么我们就要记住一定要在适当的位置注销消息,例如在ChildClosing事件中注销事件,或者在PageOnNavigatedFrom(NavigationEventArgs e)中写注销消息。

注销消息如下:

Messenger.Default.Unregister<GenericMessage<UserInfo>>( "GetUserInfo");

其实为什么不在ViewModel 中弹出窗体,其实还有一个原因,就是如果我们要在ViewModel中弹出窗体,那么我们就要知道UI中的Child,这也就是说ViewModel要引用UI,这样做就有些

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有