WPF Binding

 

 
Data Binding的几个关键概念了——

 

  1. 数据源(Data Source,简称Source):顾名思义,它是保有数据的实体、是数据的来源、源头。把谁当作数据源完全由程序员来决定——只要你想把它当做数据核心来使用。它可以是一个UI元素、某个类的实例,也可以是一个集合(关于对集合的绑定,非常重要,专门用一篇文章来讨论之)。
  2. 路径(Path):数据源作为一个实体可能保有着很多数据,你具体关注它的哪个数值呢?这个数值就是Path。就上面的例子而言,slider1是Source,它拥有很多数据——除了Value之外,还有Width、Height等,但都不是我们所关心的——所以,我们把Path设为Value。
  3. 目标(Target):数据将传送到哪里去?这就是数据的目标了。上面这个例子中,textBox1是数据的Target。有一点需要格外注意:Target一定是数据的接收者、被驱动者,但它不一定是数据的显示者——也许它只是数据联动中的一环——后面我们给出了例子。
  4. 关联(Binding):数据源与目标之间的通道。正是这个通道,使Source与Target之间关联了起来、使数据能够(直接或间接地)驱动界面!
  5. 设定关联(Set Binding):为Target指定Binding,并将Binding指向Target的一个属性,完成数据的“端对端”传输。
  1. Source:确定哪个对象作为数据源
  2. Target:确定哪个对象作为目标
  3. Binding:声明一个Binding实例 
  4. 把一根管子接到Source上并把管芯插在Source的Path上
  5. 把另一根管子接到Target上并把管芯插在Target的联动属性上

 

  1. public Window1()   
  2. {   
  3.     InitializeComponent();   
  4.   
  5.     // 1. 我打算用slider1作为Source   
  6.     // 2. 我打算用textBox1作为Target   
  7.     Binding binding = new Binding();   
  8.     binding.Source = this.slider1;   
  9.     binding.Path = new PropertyPath("Value");   
  10.     this.textBox1.SetBinding(TextBox.TextProperty, binding);               
  11. }  
把Path的设定转移到Binding的构造中:
  1. public Window1()   
  2. {   
  3.     InitializeComponent();   
  4.        
  5.     // 1. 我打算用slider1作为Source   
  6.     // 2. 我打算用textBox1作为Target   
  7.     Binding binding = new Binding("Value");   
  8.     binding.Source = this.slider1;   
  9.     this.textBox1.SetBinding(TextBox.TextProperty, binding);               
  10. }  
我们还可以为binding设些“关卡”:
  1. public Window1()   
  2. {   
  3.     InitializeComponent();   
  4.   
  5.   
  6.     // 1. 我打算用slider1作为Source   
  7.     // 2. 我打算用textBox1作为Target   
  8.     Binding binding = new Binding("Value");   
  9.     binding.Source = this.slider1;   
  10.     binding.Mode = BindingMode.TwoWay;   
  11.     binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;   
  12.     this.textBox1.SetBinding(TextBox.TextProperty, binding);               
  13. }  
 还有一个小小的提示:如果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了。
 让我们写一个这样的类:
  1. <PRE class=csharp name="code">// 第一步:声明一个类,准备必要的属性   
  2.   
  3. public class Student    
  4. {   
  5.     private int id;   
  6.     public int Id   
  7.     {   
  8.         get { return id; }   
  9.         set { id = value; }   
  10.     }   
  11.   
  12.     private string name;   
  13.     public string Name   
  14.     {   
  15.         get { return name; }   
  16.         set { name = value; }   
  17.     }   
  18.   
  19.     private int age;   
  20.     public int Age   
  21.     {   
  22.         get { return age; }   
  23.         set { age = value; }   
  24.     }   
  25.   
  26. }</PRE>  
 接下来就是使用INotifyPropertyChanged接口“武装”这个类了,注意,这个接口在System.ComponentModel名称空间中:
  1. // 第二步:实现INotifyPropertyChanged接口   
  2.   
  3. public class Student : INotifyPropertyChanged   
  4. {   
  5.     public event PropertyChangedEventHandler PropertyChanged; // 这个接口仅包含一个事件而已   
  6.   
  7.     private int id;   
  8.     public int Id   
  9.     {   
  10.         get { return id; }   
  11.         set  
  12.         {   
  13.             id = value;   
  14.             if (this.PropertyChanged != null)   
  15.             {   
  16.   
  17.                 this.PropertyChanged.Invoke(thisnew PropertyChangedEventArgs("Id")); // 通知Binding是“Id”这个属性的值改变了   
  18.             }   
  19.         }   
  20.     }   
  21.   
  22.   
  23.     private string name;   
  24.     public string Name   
  25.     {   
  26.         get { return name; }   
  27.         set  
  28.         {   
  29.             name = value;   
  30.             if (this.PropertyChanged != null)   
  31.             {   
  32.                 this.PropertyChanged.Invoke(thisnew PropertyChangedEventArgs("Name")); // 通知Binding是“Name”这个属性的值改变了   
  33.             }   
  34.         }   
  35.     }   
  36.   
  37.     private int age;   
  38.     public int Age   
  39.     {   
  40.         get { return age; }   
  41.         set { age = value; } // Age的值改变时不进行通知   
  42.     }  

OK,此时,你可以尝试使用Student类的实例作为数据源了!  

 

posted @ 2013-12-27 09:49  Mark.Yang  阅读(218)  评论(0编辑  收藏  举报