从WPF学习03:Element Binding我们可以实现控件属性与控件属性的绑定。
从WPF学习07:MVVM 预备知识之数据绑定 我们可以实现控件属性与自定义对象属性的绑定。
而以上两个功能在实际应用中还是不够的,我们经常需要将列表数据与控件属性进行绑定。
例子
ListBox切换人物,下面两个文本框跟随切换,很常用的功能。
XAML代码:
<Window x:Class="DataTemplate.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <StackPanel> <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" DisplayMemberPath="Name"/> <StackPanel HorizontalAlignment="Center" Orientation="Horizontal"> <TextBlock Text="性别:"></TextBlock> <TextBlock Text="{Binding Gender}" Margin="0 0 100 0"></TextBlock> <TextBlock Text="年龄:"></TextBlock> <TextBlock Text="{Binding Age}" Margin="0 0 100 0"></TextBlock> </StackPanel> </StackPanel> </Window>
后台代码:
public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void Notify(String propertyName) { if (PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private Int32 age; public Int32 Age { get { return age; } set { age = value; Notify("Age"); } } private String gender; public String Gender { get { return gender; } set { gender = value; Notify("Gender"); } } private String name; public String Name { get { return name; } set { name = value; Notify("Name"); } } } class People : List<Person> { public People() { this.Add(new Person() { Name = "John", Age = 30, Gender = "Male" }); this.Add(new Person() { Name = "Jake", Age = 26, Gender = "Male" }); this.Add(new Person() { Name = "Kate", Age = 25, Gender = "Female" }); } } public MainWindow() { InitializeComponent(); DataContext = new People(); }
Collection View
将例子做一些改动:
仅仅是改动了XAML。删掉了原有的ListBox,增加了一个TextBlock与两个Button
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal"> <TextBlock Text="姓名:"></TextBlock> <TextBlock Text="{Binding Name}" Margin="0 0 100 0"></TextBlock> <TextBlock Text="性别:"></TextBlock> <TextBlock Text="{Binding Gender}" Margin="0 0 100 0"></TextBlock> <TextBlock Text="年龄:"></TextBlock> <TextBlock Text="{Binding Age}"></TextBlock> </StackPanel>
数据绑定设置的路径为Name Gender Age 而当前的数据上下文却是个列表。在这种情况出现时,WPF会尝试当前数据列表的Current Item 视作绑定源。从而有了图片上的效果。
通过CollectionViewSource提供的GetDefaultView方法我们可以获得列表视图,列表视图可以使我们对列表进行包括但不限于改变Current Item的操作。
我们为两个按钮添加Handler,即可实现按钮切换人物的功能:
private void BtnToRight_Click(object sender, RoutedEventArgs e) { var view = CollectionViewSource.GetDefaultView(DataContext); view.MoveCurrentToNext(); //越界,返回 if (view.IsCurrentAfterLast) view.MoveCurrentToPrevious(); } private void BtnToLeft_Click(object sender, RoutedEventArgs e) { var view = CollectionViewSource.GetDefaultView(DataContext); view.MoveCurrentToPrevious(); //越界,返回 if (view.IsCurrentBeforeFirst) view.MoveCurrentToNext(); }
获取了列表视图后,我们还可以对数据列表进行过滤,排序等操作。在此略去例子。
IsSynchronizedWithCurrentItem
再回到文章最开始的例子中。之所以可以通过点击ListVox中的元素就能实现两个文字框内容的切换有两个原因:
1.他们的数据绑定,源相同(当前数据上下文)。
2.配置IsSynchronizedWithCurrentItem为 ture。
这样,ListControl可在SelectedItem切换时,自动切换当前绑定列表的CurrentItem。
DataTemplate简介
因为数据模板的东西太多,无法一次说完,在此先给出一个数据模板的例子。
通过数据模板,我们可以自由的定义数据的显示内容。
继续对本文开头的例子进行修改。首先要去掉该元素的DisplayMemberPath属性,该属性指定了绑定对象的哪一个属性做为Item的显示绑定对象。与数据模板功能冲突,故而去之。
改动后的效果:
改动后的XAML代码:
<Window x:Class="DataTemplate.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel HorizontalAlignment="Center" Orientation="Horizontal"> <TextBlock Text="姓名:"></TextBlock> <TextBlock Text="{Binding Name}" Margin="0 0 100 0"></TextBlock> <TextBlock Text="性别:"></TextBlock> <TextBlock Text="{Binding Gender}" Margin="0 0 100 0"></TextBlock> <TextBlock Text="年龄:"></TextBlock> <TextBlock Text="{Binding Age}"></TextBlock> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Window>