MVVM模式和在WPF中的实现(二)数据绑定
MVVM模式解析和在WPF中的实现(二)
数据绑定
系列目录:
MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
MVVM模式解析和在WPF中的实现(六)用依赖注入的方式配置ViewModel并注册消息
0x00 数据绑定要达到的效果
数据绑定要达到什么效果呢,就是在界面中绑定了数据源之后,数据在界面上的修改能反映到绑定源,同时绑定源的修改也能反映到界面上。从界面反映到绑定的数据源是很容易理解的,因为在绑定过程中我们指定了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就解耦了,谁也不依赖对方。
0x01 INotifyPropertyChanged接口
在WPF中能够实现ViewModel向View喊话功能的就是INotifyPropertyChanged接口,它就像一个大喇叭一样,我们实现了这个接口,就可以通过触发PropertyChanged事件并给出改变的数据源的对象和属性名称,以此来通知数据的变化。这个接口的实现是非常简单的,下图代码就是一种非常简易的实现方式。由于在MVVM中所有的ViewModel和部分Model都需要实现这个接口来达到绑定的效果,因此一般会专门用一个类来实现这个接口,并将这个类作为ViewModel等需要数据更改后发送通知的类的基类。
0x02 ObservableCollection<T>集合
NotifyObject貌似把一切都解决了,但是考虑这样一种情况,有一个List<string>列表显示人员名单,View中的一个ListBox绑定了这个列表。每次我们添加新成员时,为了能在View中立即看到结果必须调用RaisePropertyChanged方法让ListBox控件重新加载数据源。这种做法执行了大量的无效操作,就像我们只是改变了屏幕上一小部分内容却要刷新整个屏幕以更新显示一样。如果添加的不是人员而是一种添加动作频繁发生的操作,这种无效操作会极大影响性能。因此WPF提供了一个ObservableCollection<T>集合,可以将数据项的添加、删除等反映到View中绑定的控件上而无需我们做任何操作。所以在遇到对集合添加、删除等操作又需要使用数据绑定时要优先考虑ObservalbeCollection<T>。
0x03 数据绑定的示例
有了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模式下的数据绑定。
0x04 相关下载
示例代码:https://github.com/durow/TestArea/tree/master/MVVMTest
更多内容欢迎访问我的博客:http://www.durow.vip
MVVM模式和在WPF中的实现(二)数据绑定的更多相关文章
- MVVM模式和在WPF中的实现(一)MVVM模式简介
MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- mvvm模式下在WPF项目中动态加载项目的程序集和类
在mvvm模式的wpf项目中有个需求需要去加载解决方案的程序集,并且根据程序集去动态加载当前程序集的类,做成下拉框形式. 效果: //全局定义 private ComboBox abList= nul ...
- MVVM设计模式和在WPF中的实现(四) 事件绑定
系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中的实现(三)命令绑定 MVVM模式解析和在WPF中的 ...
- WPF中TreeView控件数据绑定和后台动态添加数据(二)
写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...
- WPF中TreeView控件数据绑定和后台动态添加数据(一)
数据绑定: 更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码. xaml代码: <TreeView Name="syntaxTree" ItemsSourc ...
- WPF中INotifyPropertyChanged用法与数据绑定
在WPF中进行数据绑定的时候常常会用到INotifyPropertyChanged接口来进行实现,下面来看一个INotifyPropertyChanged的案例. 下面定义一个Person类: usi ...
- Prism - MVVM模式下,StackPanel中增加和删除View(UserControl)
一.现实效果 在学习Prim,看官方的例子 03-CustomRegions 只是一个简单演示,这里用MVVM方式做个了相对完整的例子,实现效果如图: 点击Add,右侧StackPanel中增加一个V ...
- WPF之MVVM模式(1)
MVVM模式 一.MVVM模式概述 MVVM Pattern : Model\View\ViewModel View:视图.UI界面 ViewModel:ViewModel是对Model的封装,通过一 ...
随机推荐
- JS核心系列:浅谈 call apply 与 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- C# 破解 Reflector8.5
一.分析 破解.net .dll,可以使用reflector,但官方提供的reflector是需要购买的,因此,破解reflector势在必行. 二.破解Reflector具体步骤 下面为详细的破解步 ...
- node中子进程同步输出
管道 通过"child_process"模块fork出来的子进程都是返回一个ChildProcess对象实例,ChildProcess类比较特殊无法手动创建该对象实例,只能使用fo ...
- [干货来袭]C#6.0新特性
微软昨天发布了新的VS 2015 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下也是昨天发布的新的C#6.0的部分新特性吧.. ...
- 自己写的数据交换工具——从Oracle到Elasticsearch
先说说需求的背景,由于业务数据都在Oracle数据库中,想要对它进行数据的分析会非常非常慢,用传统的数据仓库-->数据集市这种方式,集市层表会非常大,查询的时候如果再做一些group的操作,一个 ...
- 微服务与Docker介绍
什么是微服务 微服务应用的一个最大的优点是,它们往往比传统的应用程序更有效地利用计算资源.这是因为它们通过扩展组件来处理功能瓶颈问题.这样一来,开发人员只需要为额外的组件部署计算资源,而不需要部署一个 ...
- Kotlin的android扩展:对findViewById说再见(KAD 04)
作者:Antonio Leiva 时间:Dec 12, 2016 原文链接:http://antonioleiva.com/kotlin-android-extensions/ 你也许已厌倦日复一日使 ...
- Spring异步功能
使用 Spring 的异步功能时,实质是使用的 Servlet3 及以上版本的异步功能. Spring 的异步处理机制需要在 web.xml 中全部的 servlet 和 filter 处配置 < ...
- git
CMD命令:git initgit add . [添加文件至暂存区]git commit -m '描述性语句 随意写即可'git branch gh-pages [创建仓库分支]git checkou ...
- Github使(zhuang)用(bi)指南
本文针对未能熟练使用GitHub的人员,旨在为其指明通往新世界的小路. 一些闲话可以无视 在这个开源的时代,可能你听说过GitHub,知道大概是个什么.但是,你要是不能熟练的玩起来,怎么和大神取经,怎 ...