1.基本概念:
从Windows API,MFC以来,程序是以消息驱动的,简而言之,消息的主要来源是用户的操作,比如点击鼠标,按下按钮会产生消息,而消息会被送达目标程序然后被处理,这种方式被称为消息驱动程序。后来有了.NET Framework,Winform等是以事件驱动,但是它们都是UI驱动程序,数据处于被动状态,这种方式会使得UI相关代码和数据逻辑相关代码难以分离。那么如何使得数据变被动为主动呢,在WPF中,通过Data Binding可以实现数据主动,数据回归程序的核心。
2.理解:
Binding引申意为“关联”,“键联”。在WPF程序中,Binding注重的是展示层和逻辑层间的关联关系,相当于一条高速数据公路,加工好的数据会自动送达用户界面进行展示,被用户修改过的数据也会自动传回逻辑层,一旦数据被加工好又会送达用户界面,如此不停运转,用加工好的数据驱动程序的用户界面以各种形式将数据展示出来——这就是数据驱动UI。
3.Binding简单实例:
如果把Binding比作数据公路,那公路的两端则是Source(源)以及Target(目标),一般来说,数据从逻辑层来,即Binding源是逻辑层的对象,而数据将要送达UI层,即Binding目标是UI层的控件对象。
首先,创建一个对象作为Binding的源:
class Student
{
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
}
有了源对象后,要让源对象的被关心的属性值发生变化时有能力通知Binding将数据送达UI元素,要实现这种能力就需要数据源实现INotifyPropertyChanged接口,此时,Binding会自动侦听来自这个接口的PropertyChanged事件。(被关心的属性值称为Path):
class Student:INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private int age;
public int Age
{
get { return age; }
set
{
age = value;
//激发事件
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));
}
}
}
}
Binding的Source(源)准备好后,需要准备Target(目标)。在窗体上准备一个TextBox和一个Button,TextBox作为Binding目标,点击Button时改变Student对象的Age属性值:
<Window x:Class="BindingInstance1.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:BindingInstance1"
mc:Ignorable="d"
Title="MainWindow" Height="110" Width="300">
<StackPanel>
<TextBox x:Name="textBox" BorderBrush="Black" Margin="5"/>
<Button Content="Add Age" Margin="5" Click="Button_Click"/>
</StackPanel>
</Window>
Binding的源和目标都有了,接下来就要创建连接源和目标的Binding并将它们连接起来:
public partial class MainWindow : Window
{
Student stu;
public MainWindow()
{
InitializeComponent();
//准备数据源
stu = new Student();
//准备Binding
Binding binding = new Binding();
binding.Source = stu;
binding.Path = new PropertyPath("Age");
//使用Binding连接数据源和目标
BindingOperations.SetBinding(textBox, TextBox.TextProperty, binding);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(stu.Age++).ToString();
}
}
BindingOperations.SetBinding()方法有3个参数:
-第一个参数用于指定Binding的目标
-第二个参数指明Binding把数据送达到目标的哪个属性,但这里的是一个静态只读的DependencyProperty类型成员变量(依赖属性知识点)
-第三个参数表明了使用哪个binding实例来进行关联
实际使用中,由于TextBox这类的UI元素的基类FrameworkElement对BindingOperations.SetBinding()方法进行了封装,所以,上述binding过程一般可以简写为:
public partial class MainWindow : Window
{
Student stu;
public MainWindow()
{
InitializeComponent();
this.textBox.SetBinding(TextBox.TextProperty, new Binding("Age") { Source = stu = new Student() });
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(stu.Age++).ToString();
}
}