绑定(Binding)是WPF提供的一个非常方便的特性,它可以方便的实现一个WPF的MVVM结构。
既可以实现数据驱动UI变化,也可以做到End-user在UI上的修改实现的反映到数据上。
但是有一点必须注意的是:WPF的数据基本上都是使用的引用类型,引用类型的特性就是在传递过程中,数据本体是没有变化的。
可能你对数据进行了几次不经意的传递后,对变量做的修改竟然体现在了UI的变化。这时,Debug又变成了一件很痛苦的事情(尤其是当项目比较庞大的时候)。
首先来看一个比较常见的例子。
我有一个如上图的UI,左边一个ListView,右边有一个TextBox用于编辑,代码如下:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows; namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainViewModel FViewModel = null;
public MainViewModel ViewModel
{
get { return FViewModel; }
set
{
if (value != FViewModel)
FViewModel = value;
}
}
public MainWindow()
{
InitializeComponent(); FViewModel = new MainViewModel(); this.DataContext = ViewModel;
}
} public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
DataModels = new ObservableCollection<MainDataModel>(BuildHardCodeList());
} public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] string aMembName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(aMembName));
}
} private static IEnumerable<MainDataModel> BuildHardCodeList()
{
yield return new MainDataModel() { Name = "DataModel - 1" };
yield return new MainDataModel() { Name = "DataModel - 2" };
yield return new MainDataModel() { Name = "DataModel - 3" };
yield return new MainDataModel() { Name = "DataModel - 4" };
yield return new MainDataModel() { Name = "DataModel - 5" };
} public ObservableCollection<MainDataModel> DataModels { get; set; } private MainDataModel FCurrentDataModel;
public MainDataModel CurrentDataModel
{
get { return FCurrentDataModel; }
set
{
if (value != FCurrentDataModel)
{
FCurrentDataModel = value;
RaisePropertyChanged();
}
}
}
}
public class MainDataModel
{
public string Name { get; set; } public override string ToString()
{
return Name;
}
}
}
实际运行起来后,我选中了一行以后,Name-TextBox用选中的item的Name进行了填充。
我修改了Name的内容,鼠标移到下一个TextBox。
这时发现ListView的相应记录也修改了。这就是引用类型产生的作用。
其时在大部分情况下,我们是不希望ListView的内容进行改变,直到我点击Save button。
要想实现这个需求就必须把CurrentDataModel与DataModels的连接打断掉。
现在DataModel - 1的数据存储方式如上图,堆栈中只有一份DataModel - 1, ListView与TextBox全都引用这一份数据,当TextBox进行修改时,这唯一的一份数据进行了修改,当然就会更新ListView。
要打断这种引用关系,就需要对DataModel - 1进行一次深拷贝(注意:一定是深拷贝,否则又只是一次简单的引用关系),数据的连接关系都通过深拷贝来实现,它们的关系如下图:
具体实现晚些时候有时间再放上... ...
注意WPF中绑定使用的是引用类型的更多相关文章
-
从0 开始 WPF MVVM 企业级框架实现与说明 ---- 第二讲 WPF中 绑定
说到WPF, 当然得从绑定说起,这也是WPF做的很成功的一个地方,这也是现在大家伙都在抛弃使用winform的其中一个主要原因,Binding这个东西从早说到完其实都说不完的,我先就做一些基本的介绍, ...
-
MVVM设计模式和WPF中的实现(四)事件绑定
MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
-
MVVM模式解析和在WPF中的实现(三)命令绑定
MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
-
WPF中Image控件绑定到自定义类属性
首先我们定义一个Student类,有ID,Name,Photo(保存图片路径). using System; using System.Collections.Generic; using Syste ...
-
WPF窗体视图中绑定Resources文件中字符串时,抛出:System.Windows.Markup.StaticExtension
问题描述: 在Resources.resx定义了一个静态字符串字段Title,并在WPF窗体视图中绑定为窗体的标题: Title="{x:Static local:Resources.Tit ...
-
WPF中PasswordBox控件无法绑定Password属性解决办法
在WPF中,默认的Password控件的Password属性是不允许为之绑定的,下面是一个解决绑定Password的方法的代码: 1.前台代码 <Window x:Class="Pas ...
-
WPF 在事件中绑定命令(不可以在模版中绑定命令)
其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实现将命令绑定到事件中. 上一篇中我们介绍了MVVMLight中的命令的用法,那么仅仅知道命令是 ...
-
WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题
问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...
-
MVVM设计模式和在WPF中的实现(四) 事件绑定
系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中的实现(三)命令绑定 MVVM模式解析和在WPF中的 ...
随机推荐
-
Divide and Conquer:River Hopscotch(POJ 3258)
去掉石头 题目大意:一群牛在河上的石头上跳来跳去,现在问你如何通过去掉M个石头,使得牛跳过石头的最短距离变得最大? 这一题比较经典,分治法的经典,二分法可以很方便处理这个问题,我们只要明白比较函数这 ...
-
Windows Phone 7 播放视频
在Windows Phone 7中播放视频有两种方式,一种是使用MediaElement 控件来播放,一种是使用启动器MediaPlayerLanucher来实现视频的播放.用MediaElement ...
-
九度oj 1349 数字在排序数组中出现的次数
原题链接:http://ac.jobdu.com/problem.php?pid=1349 二分.. #include<algorithm> #include<iostream> ...
-
【Delphi】圆角窗体
procedure TForm1.FormCreate(Sender: TObject); var hr :thandle; begin hr:=createroundrectrgn(1,1,widt ...
-
JavaScript中的Partial Application和Currying
这篇文章是一篇学习笔记,记录我在JS学习中的一个知识点及我对它的理解,知识点和技巧本身并不是我原创的.(引用或参考到的文章来源在文末) 先不解释Partial Application(偏函数应用)和C ...
-
20160506-hibernate入门
HQL和Criteria HQL(Hibernate Query Language) 面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写):HQ ...
-
JS基础---Dom的基本操作
DOM的增删改查 增: 1.创建一个元素节点 document.createElement() 创建新的<p> 元素:var para=document.createElement(&qu ...
-
sed 指定行范围匹配(转)
sed -n '5,10{/pattern/p}' file sed是一个非交互性性文本编辑器,它编辑文件或标准输入 导出的文件拷贝.标准输入可能是来自键盘.文件重定向.字符串或变量,或者是一个管道文 ...
-
MFC CTreeCtrl运用
CTreeCtrl运用 删除无效资源 递归的运用 自写遍历目录函数 递归遍历所有子目录 一.删除无效资源 .打开资源文件 .找到无效链接删掉 二.自写遍历目录函数 CFileFind findfile ...
-
go下载安装
https://studygolang.com/dl 一直下一步即可.