悟道MVVM 一 各施其职
MVVM,随着XAML标记语言的出现而出来的一种新的设计模式,它将WPF或Silverlight的应用程序重新进行了分层:Model – View - ViewModel。它们之间的关系是:Model为数据模型层,这里面用来放置应用程序中的实体类。ViewModel是视图模型,依懒于Model层,主要用于为View层提供数据和业务实现。在设计ViewModel层时,里面不要出现一些View中控件的状态,一切属性的设计要按业务需要来。View层中的类主要是与用户进行交互的类,这里面主要又分为这么几块:UI、Action、Trigger、Behavior、Style和Template。
在最初接触到MVVM时,我为她全新的思想所折服,一头扎进这个模式之中,项目开发中,从欣喜到困惑,再从困或到疑虑,直到现在才敢说窥探门径。其间的艰辛只有自己才能体会。一直到今天,才敢将其写入到博客中,与各位分享。希望志同道合的朋友们一起讨论,一同进步。
在MVVM之前,我早已习惯了那种逐层调用的方式,在View中调用BLL中的方法,之后获取Model,最后填充到View的Control中。这所有的操作全部都由View中Control的事件开始。也在View的事件中结束。所以,在使用MVVM的初期,遇到问题之后,总是习惯性的想用老套路来解决它。可是这样子做,却违反了MVVM的思想。其主要的原因,是没有全完了解和吃透XAML中几个主要对象的应用范围和场景,或者说没有全完撑握这些对象的工作职责。经过这段时间的应用与思考,我把自己的一些感悟写在这里,与大家一起探讨。希望集思广意,共同进步。
UI, 其职责是为用户提供一个与应用程序交互的接口。应用程序为用户的操作提供一些指引,用户通过UI为程序提供实现业务运算所需要的数据,以及操作的指令。从这个意义上来说,UI与程序之间需要交换的仅有:数据和指令。至于UI中各控件的状态与业务(ViewModel)是没有直接关系的。比如View中TreeViewItem元素是否展开,Button是否可用等等,这些职责应收UI来维护。ViewModel只是提供业务实现的接口,接收UI的数据和业务指令,完成其操作。那么,UI中各控件的状态又要如何来处理呢?
上一段中的疑问,其实在.NET中有多种方法来解决。首先,我们来分析一下,这些状态为何需要改变。
- 一,由于用户的操作,改变了控件的状态。比如,用户点击了界面上的某一个按钮(ButtonEdit),此时的UI需要把一些不希望由用户操作的控件锁起来(IsEnabled = false)。此时,我们可以通过向ButtonEdit控件添加一个EventTrigge或者Behavior,当Click事件被触发时,该触发器将会被触发,或者会执行绑定的行为。
- 二,由数据源(ViewModel)的更改,UI中的状态需要随着改变。比如,程序侦听到了来自第三方传过来的消息,希望给用户一个提示。此时,我们可以在UI中为ViewModel绑定一个DataTrigger或者PropertyTrigger。当ViewModel中,表示消息集合的属性发生变更时,触发这些触发器,在触发器中更改UI控件的状态。
在实际的项目中,我们所遇到的问题会比这上面提到的要复杂很多。但是,我们要坚守这样的一个原则,在UI中,避免使用CodeBehind的方式来更改UI的状态或完成与ViewModel的交互。我们使用Behavior,Trigger的目的是为了实现代码的复用,除非你能确定,这些代码只有当前窗体或页面使用。即便是这样,也不建议使用CodeBehind。这一点,在初学时很难把握,但我相信,随着项目经验的增加,我们会克服老框架的那种思想。虽然这个过程可能让人倍感艰难。
欢迎大家将自已使用MVVM过程中的困惑和经验拿出来与大家一起分享,相信思想的交流与碰撞可以擦出无限的火花。一起学习,共同进步!