本文摘要:
1:實體類的綁定;
2:實體類集合的綁定;
3:自定義的實體類集合,如ObservableDictionary;
4:Path的文法;
1:實體類的綁定
了解WPF資料綁定,首先需要了解接口INotifyCollectionChanged。
場景1:UI顯示學生資訊,當學生姓名發生改變的時候,就需要實時地表現到UI上。在這種情況下,就需要Student這個類實作INotifyCollectionChanged接口。如下:
public class Student : INotifyPropertyChanged
{
string firstName;
public string FirstName { get { return firstName; } set { firstName = value; Notify("FirstName"); } }
string lastName;
public string LastName { get { return lastName; } set { lastName = value; Notify("LastName"); } }
public Student(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
void Notify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
可以看到,實體類Student需要實作的INotifyPropertyChanged 接口成員為:public event PropertyChangedEventHandler PropertyChanged。當我們在WPF的UI控件中實作綁定的時候,UI會自動為PropertyChanged指派(為UI的控件對象的OnPropertyChanged)。其次,需要在屬性SET方法中實作調用委托變量PropertyChanged,即如上代碼片段中的Notify。
設計一個前台界面:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="345" Width="490">
<DockPanel x:Name="dockPanel">
<TextBlock DockPanel.Dock="Top">
<TextBlock>firstName:</TextBlock>
<TextBox Text="{Binding Path=FirstName}" Width="100"></TextBox>
<TextBlock>lastName:</TextBlock>
<TextBox Text="{Binding Path=LastName}" Width="100"></TextBox>
</TextBlock>
<Button x:Name="btnView" DockPanel.Dock="Bottom" Height="30">view</Button>
</DockPanel>
</Window>
此界面對應背景檔案:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Student student = new Student("firstname1", "lastName1");
dockPanel.DataContext = student;
btnView.Click += new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
MessageBox.Show(student.FirstName);
});
}
}
以上全部代碼實作了場景1,同時,我們還會發現,如果在UI中修改了student的FirstName或者LastName。則背景代碼中的student對象的屬性會自動同步變化。
2:實體類集合的綁定
既然對于單個實體類的資料綁定已經實作,那麼有沒有辦法對清單資料,也就是實體類集合進行資料的綁定呢?.NET提供了INotifyCollectionChanged,任何實作了該接口的集合類,都可以用來滿足如下場景。
場景2:UI顯示學生清單資訊。在背景增加或删除學生,或修改清單中單個學生的資訊,在前台都能同步顯示。同時,前台修改資料,也能同步反應到綁定源中。
在場景2的代碼中,使用了ObservableCollection集合類,這個類就是實作了INotifyCollectionChanged接口的一個集合類。
前台代碼:
<Window x:Class="WpfApplication1.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">
<DockPanel x:Name="dockPanel">
<TextBlock DockPanel.Dock="Top">
<TextBlock VerticalAlignment="Center">FirstName:</TextBlock>
<TextBox x:Name="tbFirstName" Text="{Binding Path=FirstName}" Width="150"></TextBox>
<TextBlock VerticalAlignment="Center">LastName:</TextBlock>
<TextBox x:Name="tbLastName" Text="{Binding Path=LastName}" Width="150"></TextBox>
</TextBlock>
<Button DockPanel.Dock="Bottom" x:Name="addButton">Add</Button>
<ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock Text="{Binding Path=FirstName}" Width="150"></TextBlock>
<TextBlock Text="{Binding Path=LastName}" Width="150"></TextBlock>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Window>
對應的背景代碼:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ObservableCollection<Student> students = new ObservableCollection<Student>();
students.Add(new Student("firstName1", "lastName1"));
students.Add(new Student("firstName2", "lastName2"));
this.addButton.Click += (object sender, RoutedEventArgs e) =>
{
students.Add(new Student(tbFirstName.Text.Trim(), tbLastName.Text.Trim()));
};
dockPanel.DataContext = students;
}
}
以上代碼片段,實作了場景2的所有功能。可以看到,在背景代碼中,并沒有為ListBox指定任何資料源,為何ListBox仍舊可以自動綁定資料?在WPF中,如果一個控件為綁定資料源,則會自動到父控件中去找,比如,本示例中,ListBox便會自動綁定dockPanel的資料源。而兩個TextBox,則是綁定集合類中的實體類的相關屬性。其預設綁定的是索引為0的元素。
ListBox的屬性IsSynchronizedWithCurrentItem="True"表示,如果集合類中的實體屬性在背景發生變化,則ListBox将會在UI中動态顯示變化。
3:自定義的實體類集合,如ObservableDictionary
在上文中提到了提供了,任何實作了INotifyCollectionChanged接口的集合類,都可以用來實作場景2。結果我們用到.NET提供的ObservableCollection集合類。在實際的應用中,會常常用到字典集合類,而.NET卻沒有提供。這就需要我們自己來實作一個ObservableDictionary。以下是該類的下載下傳位址:
代碼下載下傳位址:http://download.csdn.net/source/2110250。
4:Path的文法
使用 Path 屬性可以指定您要綁定到的源值:
- 在最簡單的情況下,Path 屬性值是要用于綁定的源對象的屬性名,如 Path=PropertyName。
- 通過類似于 C# 中使用的文法,可以指定屬性的子屬性。例如,子句 Path=ShoppingCart.Order 設定與對象或屬性 ShoppingCart 的 Order 子屬性的綁定。
- 若要綁定到附加屬性,應在附加屬性周圍放置圓括号。例如,若要綁定到附加屬性 DockPanel..::.Dock,則文法是 Path=(DockPanel.Dock)。
- 可以在要應用索引器的屬性名後面的方括号内指定屬性的索引器。例如,子句 Path=ShoppingCart[0] 将綁定設定為與屬性的内部索引處理文本字元串“0”的方式對應的索引。此外,還支援多個索引器。
- 可以在 Path 子句中混合索引器和子屬性;例如,Path=ShoppingCart.ShippingInfo[MailingAddress,Street].
- 在索引器内部,您可以有多個由逗号 (,) 分隔的索引器參數。可以使用圓括号指定每個參數的類型。例如,您可以有 Path="[(sys:Int32)42,(sys:Int32)24]",其中 sys 映射到 System 命名空間。
- 如果源為集合視圖,則可以用斜杠 (/) 指定目前項。例如,子句 Path=/ 用于設定到視圖中目前項的綁定。如果源為集合,則此文法指定預設集合視圖的目前項。
- 可以結合使用屬性名和斜杠來周遊作為集合的屬性。例如,Path=/Offices/ManagerName 指定源集合的目前項,該源集合包含也作為集合的 Offices 屬性。其目前項是一個包含 ManagerName屬性的對象。
- 也可以使用句點 (.) 路徑綁定到目前源。例如,Text=”{Binding}” 等效于 Text=”{Binding Path=.}”。