本例采用的是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; } }
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] 举报,一经查实,本站将立刻删除。