数据绑定要达到的效果

数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上。从界面反映到绑定的数据源是很容易理解的,因为在绑定过程中我们指定了DataContext和Binding的对象,很容易找到绑定的源并修改。但数据源修改时怎么通知界面呢?因为ViewModel中被绑定的属性并不知道谁绑定了它,如果在ViewModel中存一个View的引用,在数据发生变化时修改View,这无疑又将ViewModel和View耦合在了一起,而且这样做View中相应的控件没有开发完善难以进行测试,同样View中控件类型或名称发生改变时,ViewModel中相关代码都需要修改。在WPF中从数据源通知界面发生变化是通过发送通知的方式进行的,你可以想象一个string类型的Property,名字是TestString,在它发生变化时对着View大喊“TestString发生变化了,你们谁绑定了TestString需要跟着变啊!”,至于绑定的是TextBlock的Text,还是Label的Content,还是TextBox的Text,ViewModel并不关心,同样喊了后结果如何ViewModel也不关心。View在收到这个通知后看有没有绑定 了TestString的地方,找到了就修改,找不到就不管了,也不会在乎这个通知是哪个类型的ViewModel发的。这样ViewModel和View就解耦了,谁也不依赖对方。

INotifyPropertyChanged接口

在WPF中能够实现ViewModel向View喊话功能的就是INotifyPropertyChanged接口,它就像一个大喇叭一样,我们实现了这个接口,就可以通过触发PropertyChanged事件并给出改变的数据源的对象和属性名称,以此来通知数据的变化。这个接口的实现是非常简单的,下图代码就是一种非常简易的实现方式。由于在MVVM中所有的ViewModel和部分Model都需要实现这个接口来达到绑定的效果,因此一般会专门用一个类来实现这个接口,并将这个类作为ViewModel等需要数据更改后发送通知的类的基类。

ObservableCollection<T>集合

NotifyObject貌似把一切都解决了,但是考虑这样一种情况,有一个List<string>列表显示人员名单,View中的一个ListBox绑定了这个列表。每次我们添加新成员时,为了能在View中立即看到结果必须调用RaisePropertyChanged方法让ListBox控件重新加载数据源。这种做法执行了大量的无效操作,就像我们只是改变了屏幕上一小部分内容却要刷新整个屏幕以更新显示一样。如果添加的不是人员而是一种添加动作频繁发生的操作,这种无效操作会极大影响性能。因此WPF提供了一个ObservableCollection<T>集合,可以将数据项的添加、删除等反映到View中绑定的控件上而无需我们做任何操作。所以在遇到对集合添加、删除等操作又需要使用数据绑定时要优先考虑ObservalbeCollection<T>。

数据绑定的示例

有了NotifyObject这个基类后,我们就可以测试数据绑定了。为了让示例针对性更强,该示例仅仅用到了数据绑定,未添加命令绑定等其它内容。示例界面如图所示:

1. 拖动滑块时,最上面TextBox中的数值会跟着变化,显示滑块条的当前值,同时主界面背景色的透明度也会跟着变化。

2. 左下角的DataGrid和右下角的ListBox以及右边标签为下拉菜单的ComboBox中的数据都是一样的。选中这三个控件中的某行时,其它两个控件也会选中该项。右上方紫色方框内会显示选中行的信息。

3. 在左下角DataGrid控件、右下角ListBox控件、右上角紫色区域的某一处修改数据时,其它两处的数据也会随着修改。

下面说明如何通过数据绑定实现上面的功能。

先说一下主界面的ViewModel,其中有double型属性DoubleValue,TestData型属性SelectedData,List<TestData>型属性TestDataList。这里没有使用ObservableCollection集合因为不涉及到集合内数据项的动态添加和删除。如果要使用ObservableCollection也非常简单,只需要把List<TestData>改为ObservableCollection<TestData>即可。

功能1:Slider的Value、TextBox的Text和DockPanel的Background的Opacity都绑定了ViewModel中的DoubleValue。当拖动滑块时,Slider的Value发生了变化,会更新ViewModel中的DoubleValue,DoubleValue更新后会调用RaisePropertyChanged方法触发INotifyPropertyChanged中的PropertyChanged事件,并在事件参数中保存了发生改变的属性名称“DoubleValue”,这样View中绑定了DoubleValue的属性就要更新数据,TextBox的Text属性绑定了DoubleValue,所以TextBox更新了Text以显示最新的Slider的Value。同样主界面最顶层的布局容器DockPanel的Background中的Opacity也绑定了DoubleValue,更改后的表现就是背景色透明度发生了变化。整个过程如图中蓝色箭头所示。

功能2:DataGrid、ComboBox、ListBox的ItemsSource都绑定了ViewModel中的TestDataList,所以他们的列表项都是一样的。在DataGrid中我们显示了TestData的所有属性,ComboBox中我们只显示了StringValue属性,在ListBox中则重写了数据项模板,按照我们想要的方式显示TestData中的BoolValue、AddDateTime、和IntValue。同时这三个控件的SelectedItem也都绑定了ViewModel中的SelectedData,因此当其中一个的选中项发生改变时,其它两个控件的选中项也会相应发生改变,原理参照功能1。此外右上角紫色区域的几个TextBox和一个CheckBox分别绑定了SelectedData的不同属性,因此当SelectedData发生改变时,紫色区域内各个控件的显示内容也会发生改变。

功能3:因为TestData类也继承自NotifyObject,而且几个属性在发生改变时也会调用RaisePropertyChanged方法发出通知,因此所有绑定了这些属性的控件也会随着更新数据。表现出来就是在任何地方修改了TestData中的属性,所有绑定了这些属性的控件都会更新。

当然了,还需要在主界面的后台代码中把DataContext设置为ViewModel的一个实例。

DataContext = new MainWindowViewModel();

其实上面很多功能可以不借助ViewModel来实现的。例如功能1中把TextBox的Text直接绑定到Slider的Value上,同样功能二中ListBox的SelectedItem也可直接绑定到DataGrid的SelectedItem上,之所以使用ViewModel是为了演示MVVM模式下的数据绑定。

MVVM模式的 数据绑定的更多相关文章

  1. C# Note7:MVVM模式之数据绑定

    一.资源说明 (1)本文参考自: 一步步走进WPF的MVVM模式(二):数据绑定 WPF之数据绑定总结 二.正文  数据绑定 (Data Binding)是WPF最重要的特性之一,也是实现 MVVM( ...

  2. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  3. WPF中使用MVVM模式进行简单的数据绑定

    计划慢慢整理自己在WPF学习和工作应用中的一些心得和想法,先从一个简单的用法说起 在WPF中,XAML标记语言中绑定数据,而数据源就是指定为ViewModel类,而非界面本身的逻辑代码类 这样一定程度 ...

  4. Android进阶笔记13:RoboBinding(实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架)

    1.RoboBinding RoboBinding是一个实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架.从简单的角度看,他移除了如addXXListen ...

  5. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  6. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

  7. MVVM模式解析和在WPF中的实现(三)命令绑定

    MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  8. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  9. [转载]MVVM模式原理分析及实践

    没有找到很好的MVVM模式介绍文章,简单找了一篇,分享一下.MVVM实现了UI\UE设计师(Expression Blend 4设计界面)和软件工程师的合理分工,在SilverLight.WPF.Wi ...

随机推荐

  1. Business Cards UVALive - 4384(画图看图。。)

    只能由三种情况 都横着放  都竖着放  横和竖交错放 那就去判断好了... 具体看代码 #include <iostream> #include <cstdio> #inclu ...

  2. laravel运行慢是怎么回事?

    因为默认的 hello 页面引用了 google 的字体,至于为什么 google 这么慢就不用我详细说明了吧.

  3. BZOJ3635谈笑风生

    一些闲话 这题方法好多啊QAQ,离线有BIT.长链剖分,在线有线段树合并,主席树等. 要我出题绝对不可能放离线过... 题面链接 权限题诶 洛谷 题意简述 简单的看一下题意,就是给定\(a\),求任何 ...

  4. 【转】嵌入式Linux驱动面试题三道

    题一: Linux设备中字符设备与块设备有什么主要的区别? 字符设备:字符设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来实现这种特性.字符设备驱动程序通常至少实现open,cl ...

  5. CentOS安装oracleJDK

    实践证明,oracleJDK比openJDK快不止一星半点,换了之后立马从满负载降到个位数负载. 1.卸载openjdk # rpm -qa | grep -E '^(java|jdk)' # yum ...

  6. bzoj2757【scoi2012】Blinker的仰慕者

    题目描述 Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号.而且这些编号还隐藏着特殊的意义,即编号的各位数字之积表示这名仰慕者对Blinker的重要度. 现在Blinker想知道编号介于 ...

  7. 【MST】P2323 [HNOI2006]公路修建问题

    Description 给定 \(n\) 个点 \(m - 1\) 条无向边,每条边有两种边权,贵一点的和便宜一点的.要求至少选择 \(k\) 条贵边使得图联通且花费最大的边权值最小. Input 第 ...

  8. CentOS-5的yum源无法使用问题

    CentOS-5的yum源无法使用问题 [root@37wan ~]# yum -y install gcc Loaded plugins: fastestmirror Determining fas ...

  9. 简例s - Variables

    1. Set Variable 定义:Returns the given values which can then be assigned to a variables. 示例1: ${a}    ...

  10. [poj 1533]最长上升子序列nlogn树状数组

    题目链接:http://poj.org/problem?id=2533 其实这个题的数据范围n^2都可以过,只是为了练习一下nlogn的写法. 最长上升子序列的nlogn写法有两种,一种是变形的dp, ...