知识点
来源:http://www.360doc.com/content/12/0618/20/466494_219058999.shtml
Data Binding不应该再叫“数据绑定”,应该称为“数据关联”,意思是说,在数据和界面(或其他数据)之间具有某些关系和联动。 具体到WPF中,Binding又是怎样一种关系和联动呢?就像我们的大标题一样——Binding就是数据的“绿色通道”。“绿色通道”代表着“直接”和“快速”,Binding就是这样。

绿色通道上的“关卡”: 话说眼看就要到奥运会了,北京的各大交通要道上也都加强了安检力度。微软同学也给Binding这条“绿色通道”准备了几道很实用的“关卡”。这些“关卡”的启闭与设置是通过Binding的属性来完成的。其中常用的有:
1. <font style="color:rgb(0, 0, 255);">数据源(Data Source,简称Source):</font><font style="color:rgb(47, 47, 47);"> 顾名思义,它是保有数据的实体、是数据的来源、源头。把谁当作数据源完全由程序员来决定——只要你想把它当做数据核心来使用。它可以是一个UI元素、某个类的实例,也可以是一个集合(关于对集合的绑定,非常重要,专门用一篇文章来讨论之)。</font>2. <font style="color:rgb(0, 0, 255);">路径(Path):</font><font style="color:rgb(47, 47, 47);"> 数据源作为一个实体可能保有着很多数据,你具体关注它的哪个数值呢?这个数值就是Path。就上面的例子而言,slider1是Source,它拥有很多数 据——除了Value之外,还有Width、Height等,但都不是我们所关心的——所以,我们把Path设为Value。</font>3. <font style="color:rgb(0, 0, 255);">目标(Target):</font><font style="color:rgb(47, 47, 47);"> 数据将传送到哪里去?这就是数据的目标了。上面这个例子中,textBox1是数据的Target。有一点需要格外注意:Target一定是数据的接收者、被驱动者,但它不一定是数据的显示者——也许它只是数据联动中的一环——后面我们给出了例子。</font>4. <font style="color:rgb(0, 0, 255);">关联(Binding):</font><font style="color:rgb(47, 47, 47);"> 数据源与目标之间的通道。正是这个通道,使Source与Target之间关联了起来、使数据能够(直接或间接地)驱动界面!</font>5. <font style="color:#1D39C4;">设定关联(Set Binding)</font><font style="color:rgb(47, 47, 47);">:为Target指定Binding,并将Binding指向Target的一个属性,完成数据的“端对端”传输。</font>
- <font style="color:rgb(47, 47, 47);">如果你想把“绿色通道”限制为“单行道”,那就设置Binding实例的Mode属性,它是一个BindingMode类型 的枚举值,其中包含了TwoWay、OneWay和OneWayToSource几个值。上面这个例子中,默认地是TwoWay,所以才会有双向的数据传 递。</font>- <font style="color:rgb(47, 47, 47);">如果用户提出只要textBox1的文本改变slider1的滑块立刻响应,那就设置Binding的 UpdateSourceTrigger属性。它是一个UpdateSourceTrigger类型枚举值,默认值是 UpdateSourceTrigger.LostFocus,所以才会在移走鼠标焦点的时候更新数据。如果把它设置为 UpdateSourceTrigger.PropertyChanged,那么Target被关联的属性只要一改变,就立刻传回给Source——我们 要做的仅仅是改了一个单词,而WinForm程序员这时候正头疼呢,因为他需要去把代码搬到另一个事件响应函数中去。</font>- <font style="color:rgb(47, 47, 47);">如果Binding两端的数据类型不一致怎么办?没关系,你可以设置Binding的Converter属性,具体内容在下篇文章中讨论。</font>- <font style="color:rgb(47, 47, 47);">如果数据中有“易燃易爆”的不安全因素怎么办?OK,可以设置Binding的ValidationRules,为它加上一组“安检设施”(同样也在下篇文中讨论)。</font>
在C#代码中设置Binding


有意思的是Source端的操作,接管子和插管芯分两步,而Target端却是在SetBinding方法中一步完成。
注意:TextBox.TextProperty就是一个Dependency Property的庐山真面目。
上面的代码稍有简化的余地,就是把Path的设定转移到Binding的构造中去。

这样做的好处就是——随便你给Binding指定一个Source,只要这个Source有”Value”这个属性,binding就会自动提取它的值并传输给Target端。

一个提示:如果Source碰巧是一个UI元素,那么也可以将binding.Source = this.slider1; 改写成binding.ElementName = “slider1”; 或者
binding.ElementName = this.slider1.Name;
自定义数据源在日常项目中,经常需要自己写一个类,并且拿它的实例当作数据源。如何使得一个类成为合格的数据源?
要诀就是:
1、为这个类定义一些Property,相当于为Binding提供Path;
2、让这个类实现INotifyPropertyChanged接口。实现这个接口的目的就是当Source的属性值改变后通知Binding(否则人家怎么知道源头的数据变了并且进行联动协同呢?),从而让Binding把数据传输给Target——本质上还是使用事件机制来做,只是掩盖在底层,不用程序员去写event handler了。

此时,你可以尝试使用Student类的实例作为数据源了。
我自己的实际操作演示
首先是三部分代码展示:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WPF_Binding{public class Student : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;private int _id;public int Id{get{return _id;}set{_id = value;if(this.PropertyChanged != null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Id"));//通知Binding是"Id"这个属性的值变了}}}private string _name;public string Name{get{return _name;}set{_name = value;if(this.PropertyChanged != null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));}}}public Student(int id,string name){this.Id = id;this.Name = name;}public void Change(string name,int id){this.Name = name;this.Id = id;}}}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace WPF_Binding{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{Student stu = new Student(123, "张三");public MainWindow(){InitializeComponent();Binding binding = new Binding("Name");binding.Source = stu;binding.Mode = BindingMode.TwoWay;binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;this.textbox1.SetBinding(TextBox.TextProperty, binding);}private void button1_Click(object sender, RoutedEventArgs e){stu.Change("李四",456);}}}
其实可以直接在下面这个里面直接进行binding,只需要将
里面的 Text=”{Binding ElementName=stu,Path=Name}” 就可以了。
<Window x:Class="WPF_Binding.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WPF_Binding"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="80" Margin="77,165,0,0" TextWrapping="Wrap" Text="学生信息" VerticalAlignment="Top" Width="655" FontSize="20"/><Button x:Name="button1" Content="改变" HorizontalAlignment="Left" Margin="366,309,0,0" VerticalAlignment="Top" Width="75" IsDefault="True" Click="button1_Click"/></Grid></Window>
图形化界面设计:

运行效果:

点击改变:


