微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

silverlight开发实例Prism+MVVM+RIA五--View及ViewModel间通信

本例采用的是Prism+MVVM的模式开发,其中很重要的一点就是要解决View之间,View-viewmodel间、viewmodel间的通信问题,要解决此问题就需要使用消息机制了。本例原先是主操作界面是在Region中,后改为Window模式,类似windows操作。如下图:

具体实现也比较简单,在菜单响应事件中需要将菜单对应的URL转化为一个窗口实例对象,本例中所有的View都将继承IView接口,所有viewmodel继承Iviewmodel,所有Service对象都将继承IService接口,目前这些接口都不包含任何方法,只是为了能够使用契约名称获取实例方便同时也考虑扩展性更好些。此例的window窗口来自RadControl中的radwindow

菜单响应事件如下: 

 void OnAppSelectedChanged(T_SYS_APPLICATION selectedApp)
        {
            if (selectedApp != null && !string.IsNullOrEmpty(selectedApp.SURL) && selectedApp.IsEnabled)
            {
                radwindow view = ServiceLocator.Current.GetInstance<IView>(selectedApp.SURL) as radwindow;
                view.Header = selectedApp.SAPPLICATIONNAME;
                view.WindowStartupLocation = Telerik.Windows.Controls.WindowStartupLocation.CenterScreen;
                view.Show();
                this.eventAggregator.GetEvent<CommandEvent>().Publish(new CommandEventPara() { CommandName = "ApplicationSelectedChanged",Entity = selectedApp });
            }
        }
viewmodel示例如下:
 [Export("UserManageviewmodel",typeof(Iviewmodel))]
    public class UserManageviewmodel:MyviewmodelBase,Iviewmodel
    {
        [ImportingConstructor]
        public UserManageviewmodel(IEventAggregator _eventAggregator,IRegionManager _regionManager )
        {
            eventAggregator = _eventAggregator;
            regionManager = _regionManager;
            accountService = ServiceLocator.Current.GetInstance<IService>("AccountService") as AccountService;
            userInfoService = ServiceLocator.Current.GetInstance<IService>("UserInfoService") as UserInfoService; ;
            userService = ServiceLocator.Current.GetInstance<IService>("UserService") as UserService; ;
            userInfoService.GetUserInoListComplete += new EventHandler<EntityResultsArgs<Web.Model.V_SYS_USERINFO>>(userInfoService_GetUserInoListComplete);
            this.userInfoService.GetUserInfoListAsync();
            this.eventAggregator.GetEvent<CommandEvent>().Subscribe(OnAddUserComplete,ThreadOption.UIThread,true,p => p.CommandName == "AddUserCompleted");
            this.eventAggregator.GetEvent<CommandEvent>().Subscribe(OnEditUserComplete,p => p.CommandName == "EditUserCompleted");
            //实例化viewmodel
            ServiceLocator.Current.GetInstance<Iviewmodel>("AddUserviewmodel");
            ServiceLocator.Current.GetInstance<Iviewmodel>("EditUserviewmodel");
        }

View示例如下:

namespace SLFrameWork.Authentication.View
{
    [Export("UserManagerView",typeof(IView))]
    public partial class UserManagerView : radwindow,IView
    {
        [ImportingConstructor]
        public UserManagerView(IEventAggregator _eventAggregator)
        {
            InitializeComponent();

            this.DataContext = ServiceLocator.Current.GetInstance<Iviewmodel>("UserManageviewmodel");
        }

    }
}

下面来看看,在此用户管理中如何通过消息机制实现View与viewmodel间的通信

1、在用户管理的viewmodel中的添加按钮触发时发布消息

 ICommand addUser;
        public ICommand AddUser
        {
            get
            {
                if(addUser ==null)
                addUser = new DelegateCommand(OnAddingUser);
                return addUser;
            }
        }
        void OnAddingUser()
        {
            this.eventAggregator.GetEvent<CommandEvent>().Publish(new CommandEventPara() { CommandName = "AddUser" });
        }


2、在添加用户viewmodel中订阅消息,并实现消息触发事件,此例中消息触发时会实例化一个View(模式窗体)并弹出窗口。

[ImportingConstructor]
        public AddUserviewmodel(IEventAggregator _eventAggregator,IRegionManager _regionManager)
        {
            eventAggregator = _eventAggregator;
            regionManager = _regionManager;
            accountService = ServiceLocator.Current.GetInstance<IService>("AccountService") as AccountService;
            userInfoService = ServiceLocator.Current.GetInstance<IService>("UserInfoService") as UserInfoService; ;
            userService = ServiceLocator.Current.GetInstance<IService>("UserService") as UserService; ;
            groupService = ServiceLocator.Current.GetInstance<IService>("GroupService") as GroupService; ;
            groupService.GetGroupListComplete += new EventHandler<EntityResultsArgs<T_SYS_GROUP>>(groupService_GetGroupListComplete);
            groupService.GetGroupListAsync();
            this.eventAggregator.GetEvent<CommandEvent>().Subscribe(Onloading,p => p.CommandName == "AddUser");
        }


 

void Onloading(CommandEventPara para)
        {
            ChildWindow view = ServiceLocator.Current.GetInstance<IView>("AddUserView") as ChildWindow;
            view.Show();
        }

3、在子窗体中绑定添加用户viewmodel,同时订阅确认事件触发事件已完成窗口关闭

 [Export("AddUserView",typeof(IView))]
    public partial class AddUserView : ChildWindow,IView
    {
        [ImportingConstructor]
        public AddUserView(  IEventAggregator eventAggregator)
        {
            InitializeComponent();
            this.DataContext = ServiceLocator.Current.GetInstance<Iviewmodel>("AddUserviewmodel");
            eventAggregator.GetEvent<CommandEvent>().Subscribe(OnCompleted,p => p.CommandName == "AddUserCompleted");
        }

      private void OnCompleted(CommandEventPara para)
        {
            
            this.DialogResult = true;
        }
       

        private void CancelButton_Click(object sender,RoutedEventArgs e)
        {
            this.DialogResult = false;
        }
    }

4、在添加用户viewmodel中定义确认按钮事件

ICommand _confirm;
        public ICommand Confirm
        {
            get
            {
                if (_confirm == null)
                {
                    _confirm = new DelegateCommand(OnConfirm);
                }
                return _confirm;
            }
        }

        void OnConfirm()
        {
           
            if (ValidateData()&this.Validate())
            {
                T_SYS_USER entity = new T_SYS_USER();
                entity.SUSERNAME = this.UserName;
                entity.SPERSONID = Guid.NewGuid().ToString();
                entity.SCOMPANYCODE = this.CompanyCode;
                entity.SPHONE = this.Phone;
                entity.SMOBILE = this.Mobile;
                this.userService.AddUser(entity);

                T_SYS_ACCOUNT ut = new T_SYS_ACCOUNT();
                ut.SACCOUNTCODE = this.AccountCode;
                ut.SACCOUNTID = Guid.NewGuid().ToString();
                ut.SPASSWORD = Encrypt.MD5( this.PassWord1);
                ut.SPERSONID = entity.SPERSONID;
                accountService.AddAccount(ut);

                this.eventAggregator.GetEvent<CommandEvent>().Publish(new CommandEventPara() { CommandName = "AddUserCompleted",Entity = curUserInfo });
            }
           
        }

此处的确认事件中加入了对用户输入信息的合法性验证,满足验证则添加用户,并发布用户添加完成事件,对应的子窗体在收到事件后会关闭窗口,同时用户管理的viewmodel也会收到此事件刷新用户列表。

this.eventAggregator.GetEvent<CommandEvent>().Subscribe(OnAddUserComplete,p => p.CommandName == "AddUserCompleted");

 

void OnAddUserComplete(CommandEventPara para)
        {
            this.UserInfoList.Add(para.Entity as V_SYS_USERINFO);
        }


效果图如下:



这里需要注意的是消息发布和接收的信息需要一致,所以在订阅事件时需要对事件进行过滤,本例是对事件源的名称进行事件过滤,当然也可以制定订阅某个具体对象所发布的消息。此例中用到的事件传递的参数以封装,如下:

 public class CommandEvent : CompositePresentationEvent<CommandEventPara>
    {
        //[Export(typeof(IEventAggregator))]
        public IEventAggregator eventAggregator { get { return new EventAggregator(); } }
    }
    public class CommandEventPara
    {
        public string CommandName { get; set; }
        public object Entity { get; set; }
        public string CommnadTarget { get; set; }
        public string CommandSource { get; set; }
    }

这样就很容易进行窗口间消息传递以及事件参数的携带。

由于工作较忙,本人也没多少时间去写代码,此例也是由于个人爱好才开始边学边做,很多不完善之处,所以想要源码的朋友还请等待一段时间。今后有空再将本例中用到的自定义数据验证以及MVVM下的增删改查等功能简单说下,有兴趣的朋友可以关注下,不完善之处还请多提意见。如转载请注明出处,谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐