MVVM RelayCommand 进阶技巧 CanExcute 的使用

Command模式是设计模式中一个很重要也是十分好用的一个模式。

具体见Wiki : http://en.wikipedia.org/wiki/Command_pattern

   

SilverLight中定义了一个ICommand接口,该接口即为Command pattern的一个实现,接口定义如下:

   

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第1张图片

   

可以由上图看出CanExecute方法中用来定义命令是否可被执行的逻辑。

这个接口和我们的项目密切相关,因为RelayCommand就是ICommand接口的一个具体实现。

   

目前在我们的项目中很多ViewModel中使用了RelayCommand 并通过binding的方式将UI的操作Binding到Command上面,

但多数ViewModel只是通过Command来封装操作,而忽略了ICommand接口提供的另一个方法:CanExecute

   

RelayCommand其实并非我们使用的那么简单,它内部有着另外一个被忽略的功能。

   

让我们看一下目前RenrenUI中定义的RelayCommand中的部分代码:

我们可以清楚的看到RelayCommand类就是ICommand接口的一个具体实现,而在Execute方法被调用的时候,会首先执行CanExecute方法。

   

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第2张图片

   

我们再看一下RelayCommand的参数定义:

可以看到第二个参数为即为 Relaycommand内部 canExecute方法。

   

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第3张图片

   

这将对我们ViewModel中Command的实现产生深远的影响。(目前执行函数中首先检查网络是否可用的函数随处可见)

   

让我们看一个具体的应用场景:

   

PoiDetailViewModel 在这个页面中取得详细信息的函数为如下声明:

   

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第4张图片

这种写法在其他页面也十分常见,但此处存在一个问题,就是将CanExecute逻辑和Execute逻辑混淆在一起了,逻辑混淆意味着可维护性的降低,比如增加逻辑条件等。

同时也会导致存在大量判断是否可执行的重复代码。

   

   

我们应用前面说到的CanExecute对此进行重构:

   

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第5张图片

在调用这个方法的时候,之前的方式为:

_poiDetailViewModel.GetPoiBaseInfoByPid();
封装成Command之后相应的改为:

_poiDetailViewModel.GetPoiBaseInfoByPidCommand.Execute(null);

但这种在页面后台代码中直接调用Command不推荐,应该用Binding方式实现。

   

修改完代码后,我们在CanXXX方法内加入断点可以看到,调用时CanXXX方法确实被执行:

MVVM RelayCommand 进阶技巧 CanExcute 的使用_第6张图片

   

   

总结:

虽然看上去写CanExecute方法需要增加一个方法的定义,但是如此实现更加灵活,比如检测网络和检测用户是否登录的操作可封装在一个CanExecute

方法里面。大大增加了开发和维护成本,并且使代码更加简洁,逻辑更加清晰。

   

MVVM架构不意味着简单的将原来后台代码挪到ViewModel中,对于这个UI架构我们应做更深的了解。

   

关于RelayCommand的使用介绍到这里,具体有疑问和不同看法欢迎与我沟通。

   

   

   

   

   

   

   

   

你可能感兴趣的:(command)