WPF入门教程系列(二) 深入剖析WPF Binding的使用方法(下)

下面的内容是来自MSDN中《Binding Sources Overview》中的内容,由于怕翻译的不好而误导大家,所以分类的名称还是使用英文吧。

Using a CLR Class as the Binding Source Object

在典型的Binding情景中,一个CLR 对象作为数据源,将其中一个属性值Binding到某个UIElement的属性上(以上面显示员工姓名的情景为例。

 

XAML实现<TextBox Text=”{Binding Source=Employee, Path=EmpName}” />)。当数据源属性值变化了,相应让UIElement中对应属性变化。

 

需要实现一个中通知机制,最简单的方法是通过实现INotifyPropertyChanged接口完成此操作。具体实现,可以参考MSDN上的文章《How to: Implement Property Change Notification》。

 

其实就是实现了public event PropertyChangedEventHandler PropertyChanged;”事件,通常的做法是在上面加封装一个”protected void OnPropertyChanged(string name)”函数。在属性的set方法结尾处,调用此函数实现通知的作用。

 

如果不实行此接口,则必须自己实现一套通知系统。为你的类中的每一个想要实现通知机制的属性创建一个PropertyChanged模板。

 

即为你的每一个属性创建一个名为PropertyNameChanged事件,其中PropertyName是与这个事件对应的属性名称。然后在属性发生变化是触发这个事件。(听起来就麻烦,我也懒得去实践验证了)

 

如果以上两种方法都无法实现的话,那么就只好在你认为需要的时候显示的调用UpdateTarget方法来手动更新了。

 

(这种方法没用过,感觉已经失去了Binding的意义了)

Entire Objects Used as a Binding Source

可以理解为将整个对象作为数据源,与上一个题目的区别很小。

 

基本上可以认为是原来Binding实现的是数据源属性与UIElement属性之间的Binding,而这次是直接将一个Object对象与一个UIElement的属性进行Binding了。

 

这种情况可以使用BindingSource属性指明数据源(假设Employee对象与一个ListBox实现banding,用XAML实现<ListBox ItemsSource=”{Binding Employee}” />),或者还可以将DataContext属性设置为EmployeeDataContext属性只有UIElement的一个子类System.Windows.FrameworkElement及其子类才会有)

 

这样,在设置ItemsSource时就可以直接使用”{Binding }”这样的语法了。当然,DataContext属性设置成Employee还是需要使用DataContext=”{Binding Employee}”语句的。

 

有人在这里会嘲笑这一举动实在是��嗦,事实上,DataContext属性是非常有用的。之所以Binding对象失败而最终不得不使用C#语句进行Binding就是因为没有设置DataContext

 

因为,当我们使用{Binding Source= Employee, Path=”EmpName”}设置属性后,WPF查找Source对象是根据Element Tree逐级向上自己的Parent Element查找的,查找每一Element上的DataContext所指定的内容是否包含这一Source内容,并以第一个匹配到的结果作为最终对象。

 

也就是说,DataContext是按照Element Tree向下继承的,并且决定这WPF在运行时能否找到我们所制定的Source对象。即使我们使用{Binding Path=”EmpName”}的语句也是如此。

 

比较常见的做法是,当我们有大量的Element需要与一个数据源中的众多属性实现Binding时,我们可以直接在一个公共Parent ElementDataContext上设置这一对象(甚至可以是整个windowpage上),这将会极大的加少我们重复的代码量,同时也会是程序更加可读。

当我们需要使用的数据源是一个集合时,如果想要实现改变通知的机制。

 

同样需要实现一个接口INotifyCollectionChanged用来在集合发生改变时发起,用法单个对象是实现INotifyPropertyChanged接口类似。

 

首先是将上以前做的不是很好的那一段代码改成XAML语言实现。

 

TextBox标签中的Text属性与上面listView1中被选定的记录listView1.SelectedItem)中对应属性(例如:ContactID)做Binding

 

实现后如图所示:

<TextBox Text="{Binding ElementName=listView1, Path=SelectedItem.ContactID}" MinWidth="100" />

 

看以来代码有点长,而且,下面的几个TextBox也都存在大量的重复内容,这里就可以考虑使用上面所说的DataContext了。

listView1中被选定的记录listView1.SelectedItem)作为DataContext放在公共Parent Element上,做法如下:

 

<WrapPanel Grid.Row="1" Orientation="Horizontal" DataContext="{Binding ElementName=listView1, Path=SelectedItem}">

然后剩下的代码就可以简化很多了:

<StackPanel Orientation="Horizontal" Margin="5,2,5,2">

<TextBlock Text="ContactID:" TextAlignment="Center" />

<TextBox Text="{Binding ContactID}" MinWidth="100" />

</StackPanel>

<StackPanel Orientation="Horizontal" Margin="5,2,5,2">

<TextBlock Text="FirstName:" TextAlignment="Center" />

<TextBox Text="{Binding FirstName}" MinWidth="100" />

</StackPanel>

<StackPanel Orientation="Horizontal" Margin="5,2,5,2">

<TextBlock Text="LastName:" TextAlignment="Center" />

<TextBox Text="{Binding EmailAddress}" MinWidth="100" />

</StackPanel>

<StackPanel Orientation="Horizontal" Margin="5,2,5,2">

<TextBlock Text="EmailAddress:" TextAlignment="Center" />

<TextBox Text="{Binding LastName}" MinWidth="100" />

</StackPanel>

 

原来的SelectionChanged事件处理方法现在已经没有用了,将多余的代码去掉:

 

<ListView Name="listView1" SelectionChanged="listView1_SelectionChanged" MinWidth="280" >

 

后台代码中的对应方法也可以删掉了private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e)

 

F5 Debug运行一下,结果和原来是完全一样的。

在上一文中无得以选择使用C#实现Binding的部分代码,现在使用XAML语言实现,有几种方案可以选择,通过如下几步实现:

1) 将原先建立给listView1建立Binding那一大串代码删掉,替换成如下代码:

listView1.DataContext = dt.DefaultView;

执行结果如下图所示:

 

 

2) 将其与listView1ItemsSource属性建立Binding,设置每一列的headerDisplayMemberBinding值。

这里由于DataContext的原因,ItemsSource可以写成"{Binding }"的形式而其Children Element也都可以简写成"{Binding ContactID}"这样的形式。

<ListView Name="listView1" MinWidth="280" ItemsSource="{Binding }">

<ListView.View>

<GridView x:Name="gridView1">

<GridView.Columns>

<GridViewColumn DisplayMemberBinding="{Binding ContactID}" Header="ContactID"></GridViewColumn>

<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Header="FirstName"></GridViewColumn>

<GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="LastName"></GridViewColumn>

</GridView.Columns>

</GridView>

</ListView.View>

</ListView>

改造完后,运行结果会发现,效果和原来是一样。效率提高了,代码更加简化。

WPF入门系列教程() 深入剖析WPF Binding的使用方法(全文完

你可能感兴趣的:(WPF,binding,数据绑定)