WPF之Binding初探
初学wpf,经常被Binding搞晕,以下记录写Binding的基础。
首先,盗用张图。这图形象的说明了Binding的机理。

对于Binding,意思是数据绑定,基本用法是:
1、在xmal中使用
如下,在TextBox上绑定了Slider的Value,WPF将会机智的进行双向绑定,即TextBox和Slider中任何一方改变,另外一方也将更随跟新。
<TextBox Height="20" Margin="0,0,10,87" Text="{Binding ElementName=slider1,Path=Value}" BorderThickness="1"/>
<Slider Maximum="100" Margin="0,50,0,35" Name="slider1"/>
上面的TextBox相当与下面的。Mode就是数据绑定的方向。
<TextBox Height="20" Margin="0,0,10,87" Text="{Binding ElementName=slider1,Path=Value,Mode=TwoWay}" BorderThickness="1"/>
控制Binding数据流向的属性是Model,它的类型是BindingModel的枚举。BindingModel可以取值为TwoWay、OneWay、OneTime、OneWayToSource和Default。这里的Default指的是Binding的模式会根据目标是实际情况来确定,如果是可以编辑的(TextBox的Text属性),Default就采用双向模式。如果是TextBlock,不可编辑,就使用单向模式。
如果我们在TextBox里面输入一个恰当的值按Tab键、让焦点离开TextBox,则Slider手柄就会跳转至相应的值那里。
为什么一定要在TextBox失去焦点以后才改变值呢?这就引出了Binding的另外一个属性-----UpdateSourceTrigger,它的类型是UpdateSourceTrigger枚举,可取值为PropertyChanged、LostFous、Explicit和Default。显然,对于Text的Default行为与LostFocus一致,我们只需要把这个值改成PropertyChanged,则Slider就会随着输入值的变化而变化了。
即加入以下带代码:
UpdateSourceTrigger=PropertyChanged
注意:
顺便提一句,Binding还具有NotifyOnSourceUpdated属性和NotifyOnTargetUpdated两个bool类型是属性。如果设置为True,则在源或目标被更新以后就会触发相应的SourceUpdated事件和TargetUpdated事件。实际工作中我们可以监听这两个事件来找出来哪些数据或控件被更新了。
2、在后台c#代码中使用
等效与上面的代码
this.textbox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = slider1.Name,Mode=BindingMode.TwoWay});
或者是
this.textbox1.SetBinding(TextBox.TextProperty, new Binding("Value") { Source=slider1, Mode = BindingMode.TwoWay });
这里的ElementName与Source之间是有区别的,Source是object类型的,能接受的是一个对象,而ElementName是string型的,之恩能够接受名称。下面这样做是不行地

3、Binding的数据校验
inding的ValidationRules属性是Collection<ValidationRule>,从它的名称和数据类型我们可以得知可以为每个Binding设置多个数据校验条件,每一个条件是一个ValidationRule对象。ValidationRule是一个抽象类,在使用的时候我们需要创建它的派生类并实现它的Validate方法的返回值是ValidateionResult类型对象,如果通过验证,就把ValidateionResult对象的IsValidate属性设为true,反之,则需要将IsValidate设置为false并为其ErrorContent属性设置一个合适的消息内容(一般是字符串)。
下面这个程序的UI绘制一个TextBox和一个Slider,然后在后台C#代码中建立Binding把它们关联起来---- 已Slide为源,TextBox为目标。Slider的取值范围是0~100,也就是说我们需要验证TextBox中输入的值是不是在0~100之间。
先定义一个ValidationRule的子类。
class RangeValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
double d = ;
if (double.TryParse(value.ToString(), out d))
{
if (d >= && d <= )
{
return new ValidationResult(true, null);
}
}
return new ValidationResult(false, "ErrorContent");
}
}
然后在后台C#代码中这样定义binding。
Binding bind =new Binding("Value") { UpdateSourceTrigger= UpdateSourceTrigger.PropertyChanged,Source=slider1, Mode= BindingMode.TwoWay}; ValidationRule rule = new RangeValidationRule();
rule.ValidatesOnTargetUpdated = true;
bind.ValidationRules.Add(rule);
至于怎么在xmal中实现上面的数据校验,我还没做过,等有时间在探索。
4、关于path
尽管在XAML代码中或者Binding类的构造器参数列表中我们使用字符串来表示Path,但Path的实际类型是PropertyPath。
这样用获取Text的长度属性
Binding Path=Text.Length,ElementName=textBox1,Mode=OneWay
获取第四个字符
Binding Path=Text[3]
有的时候我们会在代码中我们看大Path是一个“.”或者干脆没有Path的Binding,着实让人摸不着头脑。原来这是一种比较特殊的情况---Binding源本身就是一种数据且不需要Path来指明。典型的string,int等基本类型都是这样,他们是实例本身就是数据,我们无法指定通过那个属性来访问这个数据,这是我们只需要将这个数据设置为.就可以了。在XAML中这个.可以忽略不写,但是在C#中编程必须要带上。
<StackPanel Height="184" Name="stackPanel1" Width="288">
<StackPanel.Resources>
<String:String x:Key="myString">
菩提本无树,何处染尘埃。
</String:String> </StackPanel.Resources>
<TextBlock Height="23" Name="textBlock1" Text="{Binding Path=.,Source={StaticResource ResourceKey=myString}}" />
</StackPanel>
或者
<TextBlock Height="23" Name="textBlock1" Text="{Binding .,Source={StaticResource ResourceKey=myString}}" />
或者
<TextBlock Height="23" Name="textBlock1" Text="{Binding Source={StaticResource ResourceKey=myString}}" />
后台C#写法
string myString = "菩提本无树,明镜亦无台。本来无一物,何处染尘埃。";
this.textBlock1.SetBinding(TextBlock.TextProperty, new Binding(".") { Source=myString});
5、最后,谈谈数据绑定一点心得
wpf的数据绑定主要是为了达到数据驱动UI的目的,说到底,还是为了通知UI,数据已经改变了。。。。
WPF的绝大多数控件都实现了INotifyPropertyChanged,所以当我们绑定两个控件时,一个控件的值改变,另一个的值也就能实时更新,这样才有了我们在上面的TextBox和Slider中改变任意一个的值,另外一个实时改变,这里为了做个验证,我在Slider上绑定一个实例属性,看看属性的值改变的时候Slider的值是不是跟着改变,理论上是不会的。
public MainWindow()
{
InitializeComponent();
//this.textbox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = slider1.Name, Mode = BindingMode.TwoWay });
this.slider1.SetBinding(Slider.ValueProperty, new Binding(".") { Source = ChangeValue });
//ValidationRule rule = new RangeValidationRule();
//rule.ValidatesOnTargetUpdated = true; }
private int changeValue=; public int ChangeValue
{
get { return changeValue; }
set { changeValue = value; }
} private void Button_Click_1(object sender, RoutedEventArgs e)
{
changeValue += ;
}
单击button并没有发现Slider的值跟着改变,这里说明ChangeValue并不是依赖属性的前提下并不能实时通知UI的Slider,自己的值改变的事。
这里就引出了依赖属性的学习。如果吧ChangeValue定义成依赖属性,就可以是实现实时通知UI的功能了。
6、在5中,我们将clr属性绑定到Slider后,发现clr属性的值改变的时候Slider的值并不会跟着改变。说明clr属性并不具有实时通知UI界面的能力。这里,我知道2种方法实现这种实时通知的功能。一种是继承INotifyPropertyChanged接口,这个接口的实现在MVVM架构里面经常拿来使用。另外一种就是WPF的依赖属性来实现了。尽管MainWindow类没有实现INotifyPropertyChanged接口,当属性的值发送改变时与之关联的binding对象依然可以得到通知,依赖属性默认的带有这种功能,天生就是合格的数据源。
我们看下用下面的代码
xmal:
<TextBox Name="textbox1" Height="20" Margin="0,0,10,87" BorderThickness="1"/>
<Slider Maximum="100" Margin="0,50,0,35" Name="slider1"/>
<Button Width="100" Height="20" Margin="10,87,407,0" Click="Button_Click_1"></Button>
c#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//this.textbox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = slider1.Name, Mode = BindingMode.TwoWay });
this.slider1.SetBinding(Slider.ValueProperty, new Binding("changeValue") { Source = this, Mode = BindingMode.TwoWay });
this.textbox1.SetBinding(TextBox.TextProperty, new Binding(".") { Source = clrValue });
//this.textbox1.SetBinding(TextBox.TextProperty, new Binding("clrValue") { Source = this });//这样写的话程序运行时textbox1是空白,不显示clrValue的初始化值
//ValidationRule rule = new RangeValidationRule();
//rule.ValidatesOnTargetUpdated = true; } private string clrValue=""; public string ClrValue
{
get { return clrValue; }
set { clrValue = value; }
} public string changeValue
{
get { return (string)GetValue(changeValueProperty); }
set { SetValue(changeValueProperty, value); }
} // Using a DependencyProperty as the backing store for changeValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty changeValueProperty =
DependencyProperty.Register("changeValue", typeof(string), typeof(MainWindow), new PropertyMetadata("")); //private int changeValue=20;
//public int ChangeValue
//{
// get { return changeValue; }
// set { changeValue = value; }
//} private void Button_Click_1(object sender, RoutedEventArgs e)
{
clrValue = "";
changeValue = "";
} }
上面的代码定义了一个clr属性clrValue和一个依赖属性changeValue,依赖属性绑定到Slider上,clr属性绑定到textbox上,button单击是两个属性的值都发生了变化,我们看看哪个的变化能实时通知到UI界面上。
程序运行时:

单击button后,发现textbox里面的值没变,而slider的值变了,说明依赖属性的值改变了能实时通知到UI。这就能力对于clr属性来说本身是没有的,如果clr属性的类实现了INotifyPropertyChange接口,那它也就具有这种能力。

一个类实现INotifyPropertyChanged接口,线面是最简的实现
class NotificationObject:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
然后需要具有通知UI能力的类只需继承自这个类就行了,这个Model的Myproperty的改变就能实现通知UI了
class Model : NotificationObject
{
private string _MyProperty = "Hello!"; public string Myproperty
{
get { return _MyProperty; }
set
{
_MyProperty = value;
this.RaisePropertyChanged("Myproperty");
}
} public void Copy(object obj)
{
this.Myproperty += " en,Hello!";
}
}
7、就上面6中的数据绑定而言,我有一些不解,先记录下来,等以后彻底理解了就来详细说明。
看代码
this.slider1.SetBinding(Slider.ValueProperty, new Binding("changeValue") { Source = this, Mode = BindingMode.TwoWay });
//this.slider1.SetBinding(Slider.ValueProperty, new Binding(".") { Source = changValue, Mode = BindingMode.TwoWay });//这样写不能实现实时通知UI
this.textbox1.SetBinding(TextBox.TextProperty, new Binding(".") { Source = clrValue });
//this.textbox1.SetBinding(TextBox.TextProperty, new Binding("clrValue") { Source = this });//这样写的话程序运行时textbox1是空白,不显示clrValue的初始化值
在上面的代码中,我发现对于依赖属性,如果使用第一行的写法,也就是Binding的双引号里面放属性名,Source里面放this,可以实现实时通知UI的功能,如果按照第二行的
写法,程序运行时能显示changeValue的初始值,而不能实现通知UI值改变的功能。
而对于clr属性来说,也就是Binding的双引号里面放点,Source里面放属性名,这样才能在程序运行时让textbox显示属性的值,乳沟按第二种写法,textbox显示的是空白。
以上两种写法导致的的差异的原因,作为新学的我来说还是不能理解,希望能尽快搞懂。
写博客真费功夫以上内容参考了很多深入浅出WPF中的内容。
WPF之Binding初探的更多相关文章
- WPF之Binding深入探讨
原文:http://blog.csdn.net/fwj380891124/article/details/8107646 1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在 ...
- WPF数据绑定Binding(二)
WPF数据绑定Binding(二) 1.UI控件直接的数据绑定 UI对象间的绑定,也是最基本的形式,通常是将源对象Source的某个属性值绑定 (拷贝) 到目标对象Destination的某个属性上. ...
- WPF的Binding功能解析
1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...
- 【转】WPF中Binding的技巧(一)
WPF中Binding的技巧(一) 在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到 ...
- WPF之Binding的使用
引出: 在WPF中Binding可以比作数据的桥梁,桥梁的两端分别是Binding的源(Source)和目标(Target).一般情况下,Binding源是逻辑层对象,Binding目标是UI层的控件 ...
- WPF之Binding深入探讨--Darren
1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...
- 深入浅出WPF之Binding的使用(一)
在WPF中Binding可以比作数据的桥梁,桥梁的两端分别是Binding的源(Source)和目标(Target).一般情况下,Binding源是逻辑层对象,Binding目标是UI层的控件对象:这 ...
- WPF之Binding【转】
WPF之Binding[转] 看到WPF如此之炫,也想用用,可是一点也不会呀. 从需求谈起吧: 首先可能要做一个很炫的界面.见MaterialDesignInXAMLToolKit. 那,最主要的呢, ...
- WPF之Binding深入探讨 转载:http://blog.csdn.net/fwj380891124/article/details/8107646
1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...
随机推荐
- 如何使用DOS命令(cd命令)
如何使用DOS命令 DOS是Disk Operation System(磁盘操作系统)的简称,是个人计算机上的一类操作系统.它直接操纵管理硬盘的文件,一般都是黑底白色文字的界面.顾名思义,DOS主要是 ...
- php 远程本地化无后缀图片
$body = '<p style="margin: 0px 0px 1.1em; padding: 0px; color: rgb(51, 51, 51); font-family: ...
- Python Day13
堡垒机 权限管理 当你公司的服务器变的越来越多后,需要操作这些服务器的人就肯定不只是一个运维人员,同时也可能包括多个开发人员,那么这么多的人操作业务系统,如果权限分配不当就会存在很大的安全风险,举几个 ...
- SharePoint Online 申请试用链接地址
SharePoint Online 申请试用链接地址: https://products.office.com/en-us/business/compare-office-365-for-busine ...
- 【转】真正从零开始,TensorFlow详细安装入门图文教程!(帮你完成那个最难的从0到1)
AI这个概念好像突然就火起来了,年初大比分战胜李世石的AlphaGo成功的吸引了大量的关注,但其实看看你的手机上的语音助手,相机上的人脸识别,今日头条上帮你自动筛选出来的新闻,还有各大音乐软件的歌曲& ...
- Web API系列(一)设计经验与总结
在移动互联网的时代, Web服务已经成为了异构系统之间的互联与集成的主要手段,各种 Web服务几乎都采用REST风格的Web Api来构建. 通过Http协议的形式来. 以Get/Post方式发送请求 ...
- Swift3.0变化分享
Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...
- asp.net core 如何在Controller获取配置文件的值
场景:我们会把一些配置信息,写在配置文件文件中,便于我们修改和配置.在之前的asp.net 中可以通过ConfigurationManger来获取web.config里面的配置.在.net core ...
- Altium Designer 的entry sheet ,offsheet和port作用(转载)
1.图纸结构 图纸包括两种结构关系: 一种是层次式图纸,该连接关系是纵向的,也就是某一层次的图纸只能和相邻的上级或下级有关系: 另一种是扁平式图纸,该连接关系是横向的,任何两张图纸之间都可以建立信号连 ...
- 导出excel报错
System.ComponentModel.Win32Exception: 拒绝访问 1.问题现象: foreach (System.Diagnostics.Process thispro in Sy ...