初学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初探的更多相关文章

  1. WPF之Binding深入探讨

    原文:http://blog.csdn.net/fwj380891124/article/details/8107646 1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在 ...

  2. WPF数据绑定Binding(二)

    WPF数据绑定Binding(二) 1.UI控件直接的数据绑定 UI对象间的绑定,也是最基本的形式,通常是将源对象Source的某个属性值绑定 (拷贝) 到目标对象Destination的某个属性上. ...

  3. WPF的Binding功能解析

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  4. 【转】WPF中Binding的技巧(一)

    WPF中Binding的技巧(一)   在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到 ...

  5. WPF之Binding的使用

    引出: 在WPF中Binding可以比作数据的桥梁,桥梁的两端分别是Binding的源(Source)和目标(Target).一般情况下,Binding源是逻辑层对象,Binding目标是UI层的控件 ...

  6. WPF之Binding深入探讨--Darren

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  7. 深入浅出WPF之Binding的使用(一)

    在WPF中Binding可以比作数据的桥梁,桥梁的两端分别是Binding的源(Source)和目标(Target).一般情况下,Binding源是逻辑层对象,Binding目标是UI层的控件对象:这 ...

  8. WPF之Binding【转】

    WPF之Binding[转] 看到WPF如此之炫,也想用用,可是一点也不会呀. 从需求谈起吧: 首先可能要做一个很炫的界面.见MaterialDesignInXAMLToolKit. 那,最主要的呢, ...

  9. WPF之Binding深入探讨 转载:http://blog.csdn.net/fwj380891124/article/details/8107646

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

随机推荐

  1. Jackson 通过自定义注解来控制json key的格式

    Jackson 通过自定义注解来控制json key的格式 最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换.而这个替换过程是需要依赖一个第三方的dubbo服务的.为了使得这个转换 ...

  2. SWMM模型子汇水区划分的几种方法

    子汇水区的划分是SWMM模型建模的主要步骤之一,划分的好坏对结果精度有比较大的影响.概括来讲,子汇水区的划分有以下几种思路: (1)根据管网走向.建筑物和街道分布,直接人工划分子汇水区.这个方法适用于 ...

  3. PHP安装kafka插件

    在工作中我们经常遇到需要给php安装插件,今天把php安装kafka的插件的步骤整理下,仅供大家参考 1:需要先安装librdkafka git clone https://github.com/ed ...

  4. Visual SVN 5.01 Po jie 笔记

    最近搞项目要与几个同事一起coding,鉴于代码的合并和提交的问题,所以要搞个版本管理.由于是私有的项目,所以退git 求SVN了.装了乌龟和Visual SVN,才发现Visual SVN的客户端不 ...

  5. 条件编译#if

    1.为什么需要条件编译 客户的需求在不停地发生变化,一会儿需要这个功能,一会儿不需要这个功能.我们可以使用条件编译来方便地裁剪功能. 2.条件编译语句#if 条件编译语句#if的形式是 #if exp ...

  6. MySQL性能优化:索引

    MySQL性能优化:索引 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序.数据库使用索引以找到特定值,然后顺指针找到包含该值的行.这样可以使对应于表的SQL语句执 ...

  7. npm 发布到远程资源库

    一.npm 发布到远程资源库 1.创建package.json Package.json 属性说明 name - 包名. version - 包的版本号. description - 包的描述. ho ...

  8. 2MyBatis入门--深入浅出MyBatis技术原理与实践(笔记)

    什么是 MyBatis ? MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

  9. 关于C中内存操作

     from:http://blog.csdn.net/shuaishuai80/article/details/6140979 malloc.calloc.realloc的区别 C Language ...

  10. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...