MvvmLigth框架利器之INavigationService

Cle****-he UID.1073626
2015-11-24 发表

标题有点唬人哈,其实是我自己按照平时UWP/WP项目开发的使用经验给INavigationService加封的,由于网络中关于Mvvmlight框架的INavigationService的资料比较少,所以在此做个笔记,一来记录知识以防忘记,二来希望对用到INavigationService的朋友有所帮助。

Mvvmlight在平时开发中最常用到的利器有五个:

1、ViewModelBase VM鼻祖
2、RelayCommand命令
3、Messenger消息通知
4、DispatcherHelper 多线程处理
5、INavigationService导航服务

ViewModelBase VM基类,里面提供了VM中常用的方法。

RelayCommand命令,这东西在UWP出来之前使用率是很高的,UI上的Command绑定VM方法是必须用到RelayCommand,用来解耦很是方便实用,不过UWP中基本就用不到它了,UWP中的UI事件可以直接绑定到方法名,RelayCommand便从此可以在UWP项目代码中退隐江湖了。

Messenger消息通知,这个谁用谁知道,不过建议大家用的时候仔细考虑下要做的Action是否超出了VM本身的职责,不然不要滥用,不然项目逻辑太过于分散。Messenger的设计初衷就是用来使VM与View能够相互通信,VM告诉View我事情做完了接下来你要接着做你的事情,这种情况下才适合使用Messenger,千万不要在VM内部滥用Messenger。

DispatcherHelper多线程处理,这个用来帮助我们在非UI线程上处理UI线程对象的帮助类,也非常好用。

前四个本文章内不做过多的讲解,本文的主要内容是INavigationService的使用。

INavigationService导航服务,这家伙是为了项目解耦、平台自适应而诞生的。它的作用主要是用来导航界面(这不是废话么),但最重要的是它能在VM中直接发起导航界面来完成导航。让导航脱离具体的Page对象,减少了VM与View的耦合,而且还不受平台的限制,使用它进行导航,即使平台之间各自导航的方法各异,也完全不受影响。

好处都说了多么多,那具体该怎么使用呢?想要使用INavigationService需要先在SimpleIoc.Default中注册一个NavigationService对象,NavigationService对象继承与INavigationService,提供了常用的导航方法如下:

[mw_shl_code=csharp,true]public void GoBack();
public void NavigateTo(string pageKey);
public virtual void NavigateTo(string pageKey, object parameter);[/mw_shl_code]

而NavigateTo导航方法中需要提供的是string类型的参数,通过该参数与Configure属性中具体的Page映射关系来确定要导航到哪一页。

打开ViewModelLocator类文件在Ioc容器中注册NavigationService对象,具体代码如下:

[mw_shl_code=csharp,true]public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

//注册VM
SimpleIoc.Default.Register<MainPageViewModel>();
SimpleIoc.Default.Register<Page1ViewModel>();
SimpleIoc.Default.Register<Page2ViewModel>();

//注册导航服务对象
SimpleIoc.Default.Register(InitNavigationService);

}

/// <summary>
/// 创建NavigationService对象
/// </summary>
/// <returns>NavigationService</returns>
protected INavigationService InitNavigationService()
{
var service = new NavigationService();

service.Configure(typeof(MainPageViewModel).FullName, typeof(MainPage));
service.Configure(typeof(Page1ViewModel).FullName, typeof(Page1));
service.Configure(typeof(Page2ViewModel).FullName, typeof(Page2));

return service;
}[/mw_shl_code]

注册NavigationService对象和注册VM是一样的,我们通过InitNavigationService()方法来返回一个NavigationService实例对象,并在Configure中注册页面与key之间的映射,这里推荐使用typeof(MainPageViewModel).FullName的方式设置key,好处不言而喻,防止用的时候写错QAQ

添加完key/Page映射,注册完NavigationService对象后,在ViewModelLocator类中添加一个用来获取刚才注册的NavigationService对象的属性
[mw_shl_code=csharp,true]/// <summary>
/// 导航服务器
/// </summary>
public INavigationService NavigationService => ServiceLocator.Current.GetInstance<INavigationService>();[/mw_shl_code]

至此,配置的工作已完成,使用的时候很简单,直接根据key去导航,如下:

[mw_shl_code=csharp,true]//进行导航
ViewModelLocator.Default.NavigationService.NavigateTo(typeof(Page1ViewModel).FullName, "这里也可以填写参数");[/mw_shl_code]

虽然可以填写参数,但是不建议在此传递参数,为什么呢?因为在此传参的话,Page中就必须重写OnNavigatedTo方法来获取该参数,这样就会增加VM与View之间的耦合度。

既然使用了MvvmLight框架那么这种情况是不允许让它发生的。很简单,MvvM的设计模式的一个核心理念就是数据驱动界面,把数据的地位放到第一位,任何界面的变化都是由于数据发生了变化,而不是以前的事件驱动机制使用事件来操作数据的变化。从而MVVM中诞生了数据绑定、集合数据变更通知等一些技术。

这里推荐大家在传递数据时不妨考虑直接去修改数据,你传递过去不也是为了给一个对象赋值么?所以在这里可以给要跳转的界面的VM中的某个属性赋值,然后让UI再去绑定这个属性,属性值变化了,UI当然也会跟着变化,这就是数据驱动机制。

所以传参可以这样:
[mw_shl_code=csharp,true]//为要跳转界面的VM 的属性赋值
ViewModelLocator.Default.Page2ViewModel.NavigateParameter = "我是参数";
ViewModelLocator.Default.NavigationService.NavigateTo(typeof(Page2ViewModel).FullName);[/mw_shl_code]

效果图:
***图片停止解析***

本文出自:53078485群大咖Aran

敬告:
为防止不可控的内容风险,本站已关闭新用户注册,新贴的发表及评论;
你现在看到的内容只是互联网用户曾经发表的言论快照,仅用于老用户留存纪念,且仅与科技行业相关,全部内容不代表本站观点及立场;
本站重新开放前已针对包括用户隐私、版权保护、信息安全、国家政策在内的各种互联网法律法规要求,执行了隐患内容的自查、屏蔽和删除;
本站目前所属个人主体,未有任何盈利安排与计划,且与原WFUN.COM所属公司不存在任何关联关系;
如果本帖内容或者相关资源侵犯到您的合法权益,或者您认为存在问题,那么请您务必点此举报或投诉!
全部回复:
391695558 UID.256000
2015-11-24 使用 Lumia 1520 回复

虽然不懂,但支持!

tmp00000 UID.995403
2015-11-24 回复

vm跳转这个功能在应用定义类就搞定了...在App.xaml.?? 添加Frame后注册导航事件,公开一个静态导航方法。跟具体的页面无耦合。

赧****月 UID.1258880
2015-12-15 回复


vm跳转这个功能在应用定义

本站使用Golang构建,点击此处申请开源鄂ICP备18029942号-4联系站长投诉/举报