從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>