博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MVVM 开发的几种模式讨论(WPF)
阅读量:7087 次
发布时间:2019-06-28

本文共 3733 字,大约阅读时间需要 12 分钟。

  在WPF系(包括SL,WP或者Win8)应用开发中,MVVM是个老生常谈的问题。初学者可能不会有感觉,但当你写一个核心逻辑能在各种平台上无缝移植,而只需改改UI的时候,那种快感是无法用语言来形容的。

   笔者当初接触时,对MVVM并不以为然,编了很多代码以后,反过来看MVVM for WPF的经典文章以后,才若有顿悟。标准的MVVM把程序分成了Model, ViewModel和 View三个部分,但方法是死的,人是活的。我一般的做法是逻辑写一个,View写一个,没有那么严格。为了方便讨论,我们把ViewModel和Model合称Model, View还是View, 分别代表逻辑和界面。分离是肯定的,可是在程序中终究是要把View和Model在某个地方结合起来。 本文就讨论下几种结合的方式。

1. 标准MVVM(由View实例化Model)

     标准的MVVM,做法当然是先设计Model, 然后再设计View, 在View的代码里有且仅有这么几句话:

复制代码
public partial class PluginMangerUI : UserControl    {             public PluginMangerUI()        {            this.InitializeComponent();            PluginManager manager = new PluginManager();            this.DataContext = manager;        }    }
复制代码

 

基本的逻辑结构可以用下图来表示。不同的库是由自底向上的方式设计的。

    这种由View调用Model, 并具体由View负责Model实例化的方式是最为普遍的,非常适合于需要跨平台的应用。当然,Model并不知道View的存在,因此View要承担所有的界面逻辑,好在WPF已经给出了足够多的解决方案,触发器,模板。基本绝大多数需求都能满足。

2. 插件结构(Model实例化View)

     这种做法,是笔者经常用的。在Model里,通过以下代码来实现界面生成

复制代码
internal class ViewExample : UserControl { }    public class ModelExample : IView    {        private readonly ViewExample view;        public ModelExample()        {            this.view = new ViewExample();        }        public object UserControl        {            get            {                return this.view;            }        }
复制代码

 

   肯定会有同学问道,怎么会有这么奇怪的写法?这种做法的最常见场合应该是插件系统。一个个的Model其实是一个个的插件,它们应该具备自治性。因此,应该由自身负责界面的产生。

   它的好处是可以通过Model更加精细的调节View的行为,你可以在任何时候获得View内部ListBox的SelectIndex, 而不用麻烦的用Binding。 打个比方说,游戏开发中,你需要随时控制物体的运动速度和方向,这样Model就必须控制View. 绑定很难解决这类问题。

   我不知道有多少同学在WPF中使用插件的设计思想。若按插件的思路,库应该按功能划分。在这种设计思路下,不同的库便不是自下而上的分层了,而是通过领域和功能分层,如下图:

  每一个功能库都有完整的自治性,当你将该功能库拷贝到主框架之下时,它就会自动加载,由Model负责View的生成。一切合情合理。

  3. 组装车间(第三方组装View和Model)

   这种思路来自于工厂方法,类似于装配车间,View和Model都不负责互相的实例化。而有一个“管理器”负责组装它们。这样的好处在于可配置。你可以通过配置文件动态的改变View.

    我记得一种比较著名的WPF向导(Wizard)就是这样的设计思路:

复制代码
private static List
> CreateSteps(DataProcessTask o) { var welcomeModel = new WelcomeModel(o); var step1ViewModel = new UserCoreModel(o); var step2ViewModel = new UserDataModel(o); var step3ViewModel = new ConnectModel(o); var step6ViewModel = new FinishModel(o); return new List
> { /// Each step contains a ViewModel and a View type (the type representing the actual Xaml to be shown). new CompleteStep
{ViewModel = welcomeModel, ViewType = typeof (Welcome), Visited = true}, new CompleteStep
{ViewModel = step1ViewModel, ViewType = typeof (UserCore)}, new CompleteStep
{ViewModel = step2ViewModel, ViewType = typeof (UserDataView)}, new CompleteStep
{ViewModel = step3ViewModel, ViewType = typeof (Connect)}, new CompleteStep
{ViewModel = step6ViewModel, ViewType = typeof (Finish)} }; }
复制代码

 

    如上图所示,DataProcessTask类是控制整个流程的核心,第一步先实例化所需的ViewModel, 第二部,通过构建一个List列表,将View的Type的方法传到列表中。最终管理器通过反射来实例化View,并将DataContext绑定到对应的ViewModel完成整个组装过程。

    可以看出,这种做法彻底的隔绝了View和Model, 同时通过配置选项,可以随时修改View。可谓是一种不错的设计。 但是,必需看到,对于View来说,Model没有任何管理的权限。下图展示了它的基本逻辑:

  如果最终你依旧需要两边互相控制,可以考虑采用dynamic关键字。

4. 总结

    其实没有哪种方式是最好的,完全是看你对整个系统的设计需求。但不论如何,界面和逻辑的分离,这是毋庸置疑的。下面的表格总结了几种做法的特点和适用场合:

名称 组装逻辑 适用场合 缺点 备注
标准MVVM View实例化Model 常用的跨平台场合 Model无法控制任何View 适用于自底向上的分层设计
Model实例化View Model实例化View 插件结构或用于游戏开发 存在一定的耦合 适用于按功能划分的插件型类库设计,或要求Model大量控制View的场合
组装车间 第三方管理器实例化和组装Model和View 可动态替换所有View 两者彻底隔绝,没有控制灵活性 大型系统的严格设计

    当然,如果用MVVMLight等第三方类库的话,就应该按照它的方案去开发。但我们的原则是,解决问题,但不要引入更复杂的问题。为了解耦,搞了大量的复杂逻辑,反而舍本逐末。

    有任何问题,欢迎随时讨论。

作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

标签:
本文转自FerventDesert博客园博客,原文链接:http://www.cnblogs.com/buptzym/p/3220910.html,如需转载请自行联系原作者
你可能感兴趣的文章
用javascript实现网站来回撞动的广告图片
查看>>
boost bimap 学习笔记
查看>>
子串计算 --2010北京大学复试机试题
查看>>
dynamic、object、var 之间的区别
查看>>
[sqllite]c语言操作sqlite一: 连接sqlite数据库
查看>>
Scintilla and SciTE
查看>>
学习之路十五:C#基础知识简单梳理
查看>>
最近很忙
查看>>
Html中table显示空单元格的方法及table标签属性总结
查看>>
WPF 获取文件运行目录
查看>>
使用emma对web工程进行测试覆盖率检查
查看>>
android activity生命周期
查看>>
距离和相似度度量[转]
查看>>
mysql在创建存储函数时报错
查看>>
ADO.net DataTable 和Amazon SimpleDB的相互转换
查看>>
【英语天天读】Choose Optimism
查看>>
恢复Ext3下被删除的文件(转)
查看>>
Direct3D 开发之旅 3D 游戏基本概念的介绍1
查看>>
sc windows服务常用命令
查看>>
如何使用ftp从Metalink上下载补丁
查看>>