浅谈MVVM数据绑定的耦合性

2016-06-02 08:07朱立北京信息职业技术学院北京100018
中国科技纵横 2016年1期
关键词:耦合

朱立(北京信息职业技术学院,北京 100018)



浅谈MVVM数据绑定的耦合性

朱立
(北京信息职业技术学院,北京 100018)

【摘 要】复杂软件需要清晰合理的架构设计,否则会给前期开发和后期维护带来极大的困难。各类框架的应运而生,重要目的之一就是降低软件的耦合度以获得良好的性能。本文围绕近年来流行度较高的MVVM架构,简单介绍了其原理和特点,针对MVVM数据绑定的耦合性,分别例举逐一属性绑定、对象绑定和集合绑定,并针对不同的绑定配置方式分析了耦合性。

【关键词】MVVM 数据绑定 耦合

对软件来说,最基本、最核心的内容是数据,所有代码层次的划分都是围绕数据设计的。业务逻辑层是为了实现对数据的增删改查,各类界面技术是为了更好地呈现数据。随着软件复杂度的提高,要想降低数据层、业务逻辑层及界面层的耦合度,就需要良好的架构设计。ORM等框架实现了业务逻辑层和数据层之间的解耦合,另有一批框架用来解决业务逻辑层和视图之间的耦合问题,MVVM就是其中之一。

1 认识MVVM

Model-View-ViewModel(MVVM,模型-视图-视图模型)是一种架构模式,如图1所示。MVVM的目标是将几乎所有程序代码从视图中移除(更加彻底的代码后置)。交互设计师只需专注于使用XAML(视图)表达用户体验需求,并创建视图和视图模型的绑定;而模型和视图模型则由程序员进行开发和维护。

MVVM的视图具有独立性,其中的控件能够管理部分用户输入并且自行反应。用户输入经过视图底层系统的处理和分发,多以事件的形式被后台用户程序所感知。视图模型包含概念模型而不是数据模型,所有业务逻辑和其它操作都是在模型和视图模型里完成的。

长久以来,在非MVVM架构中直接编写代码存在两个问题。一,View中有些控件的数据类型和Model中的属性类型不同。例如性别,Model中通常设置为bool类型;而View中呈现的是“男”、“女”这样的字符串,这就需要额外的代码进行转换。而转换代码如果放在View中会增大软件的耦合度(View上不应出现逻辑代码);放在Model中,会导致Model臃肿庞大。二、事件驱动开发中的复用问题。Winform开发中的事件驱动因其易于理解和实现而被广泛接受,问题就是多种同类事件并存,后期维护繁重,且代码复用性相对较差。

图1 MVVM结构关系图

Model和View中间的辅助角色——ViewModel较好地解决了上述两个问题。它帮助View和Model之间进行数据转换,并保证数据类型适当。同时它也将View的多种命令绑定到Model中相同的处理方法上,使得这些命令中绑定的方法可以被其他View复用。与同类架构模式(MVP、MVC)相比,MVVM架构唯一不同的特点是它采用双向绑定,即View中的变动会自动反映在ViewModel中,反之亦然。

2 MVVM的数据绑定

MVVM的一个主要特征是,通过Binding机制由ViewModel指示View如何作变更;用户与ViewModel的交互通过Command来实现,这时只需View指导ViewModel即可,而ViewModel不必关心View如何展示和展示什么,它只需提供属性(要绑定的数据和Command)并实现INotifyPropertyChanged。少了一个方向的依赖,代码自然更简洁清晰。

View中的控件存在一个属性“DataContext”,负责为控件指定数据源头。DataContext属性给控件指定一个后台模型,就是该控件的数据来源。ViewModel就是这个后台模型,给View中的控件提供用于显示的数据。而ViewModel提供的数据应该来自于背后的Model。所以,三者的关系是根据View中显示的数据是何种Model,来定义ViewModel。

Model中的某个类要成为真正的数据源,需要实现以下两个步骤。

(1)在后台.cs文件(以下简称后台)中为该类定义属性。如:

(2)让该类实现INotifyPropertyChanged接口。实现该接口的目的是当数据源的属性值改变后通知Binding(使其知道源数据变了并进行联动协同),以便Binding把数据传输给目标。实际上,这个动作本质上还是运用了事件机制,只是掩盖在底层,不用程序员去写代码。

具体的绑定需要在前台页面文件(以下简称前台)和后台(如MainPage类的构造函数中)分别进行配置:

后台配置:

前台配置:

〈TextBox x:Name="tb1" Text="{Binding Names}"〉〈/ TextBox〉语句的含义是,名称为tb1的文本框的Text属性值与Names属性值相关联,Names变化的时候,Text也随之变化。

这里面蕴含了“数据驱动界面”的模型。在这里,Names属性值是数据源,文本框tb1用来显示数据,Names属性值驱动文本框tb1的Text进行改变;人为改变文本框tb1的Text属性值,也会被送回到person对象的Names属性上去。这里的Text属性也叫“依赖式属性”,就是它本身没有值,它的值“依赖”在其它对象的属性值上,通过Binding进行传递和转换。这样做的好处是,随便给Binding指定一个数据源,只要这个数据源有名为“Names”的属性,Binding就会自动提取它的值并传输给Text。

3 绑定的耦合性分析

不同配置的数据绑定会呈现不同的耦合性。在上述例子中,需要将前台页面中的控件逐一绑定到person对象的每个属性,属性越多,绑定越多,前后台的耦合度也就越高。在数据结构复杂度很高的情况下,这种方式显然不可取。可以采取下列方式进行改进。

后台文件:

前台文件:

这个绑定是将前台页面(Page就是App.MainPage,所以可以在类代码中使用this)绑定到person对象(包含所有的属性)上,该页面的所有控件就可以直接获取该对象的所有属性值而不必单独进行绑定,耦合度大大降低。

〈TextBox Text="{Binding Names}"〉〈/TextBox〉语句中,Text属性绑定的Names属性是从所在页面(已经绑定了person对象)获取的,而不是后台类对象,所以这里不构成耦合。

如果后台数据结构不是单一对象而是集合,并且是存在上下级关系的复杂集合,用这种改进的方法也存在前后台耦合度过高的问题(集合中的每个对象都要逐一与前台页面进行绑定)。这时可以采取集合绑定的方法。

后台文件:

前台文件:

在上例的前台文件中,只有Source="{Binding Company.Departments}" x:Key= "cvsDeps"〉这一个绑定与后台构成了耦合,它绑定了后台集合对象Company.Departments。后续的绑定都是调用这个复杂集合的下级对象。虽然调用关系复杂,但耦合度并没有提高。

4 结语

通过分析可以看出,绑定的设置方式不同,前后台的耦合度也会不同。而绑定设置方式应该结合数据结构的复杂程度和数据展示的需求进行考虑。软件的灵魂是数据,最终要在满足需求的情况下保证软件性能。

参考文献:

[1]刘黎志,陈传波.Windows Phone数据访问技术研究.计算机工程与科学[J],2014,36(9).

[2]陈涛.MVVM设计模式及其应用研究.计算机与数字工程[J].2014, (10).

作者简介:朱立,女,北京信息职业技术学院,副教授,硕士,软件技术、高职教育研究方向。

猜你喜欢
耦合
非Lipschitz条件下超前带跳倒向耦合随机微分方程的Wong-Zakai逼近
Riketake混沌系统线性耦合同步
基于改进SBELM的耦合故障诊断方法
厌氧氨氧化与反硝化耦合脱氮除碳研究Ⅰ:
基于Virtual.Lab下消声器声固耦合的模型建立
多星座GNSS/INS 紧耦合方法
基于“壳-固”耦合方法模拟焊接装配
基于CFD/CSD耦合的叶轮机叶片失速颤振计算
一种可变耦合数控跳频滤波器电路设计
求解奇异摄动Volterra积分微分方程的LDG-CFEM耦合方法