WPF and Silverlight 学习笔记(二十):WPF数据绑定概述
WPF數據綁定為應用程序提供了一種表示數據和與數據交互的簡單而又一致的方法。元素能夠以公共語言運行庫 (CLR) 對象和 XML 的形式綁定到各種數據源中的數據。
一、數據綁定的基本概念:
數據綁定涉及到兩個方面:一個是綁定源,再一個是綁定目標。綁定源即控件綁定所使用的源數據,綁定目標即數據顯示的控件。
1、對于綁定源,在WPF可以是以下四種:
- CLR對象:可以綁定到CLR類的公開的屬性、子屬性、索引器上
- ADO.Net對象:例如DataTable、DataView等
- XML文件:使用XPath進行解析
- DependencyObject:綁定到其依賴項屬性上,即控件綁定控件
2、對于綁定目標,必須是WPF中的DependencyObject,將數據綁定到其依賴項屬性上。
二、綁定的基本方式
根據數據流的方向,WPF中的數據綁定分為以下四種:
-
OneWay 綁定導致對源屬性的更改會自動更新目標屬性,但是對目標屬性的更改不會傳播回源屬性。此綁定類型適用于綁定的控件為隱式只讀控件的情況。例如,您可能綁定到如股票行情自動收錄器這樣的源,或許目標屬性沒有用于進行更改的控件接口(如表的數據綁定背景色)。如果無需監視目標屬性的更改,則使用 OneWay 綁定模式可避免 TwoWay 綁定模式的系統開銷。
-
TwoWay 綁定導致對源屬性的更改會自動更新目標屬性,而對目標屬性的更改也會自動更新源屬性。此綁定類型適用于可編輯窗體或其他完全交互式 UI 方案。大多數屬性都默認為 OneWay 綁定,但是一些依賴項屬性(通常為用戶可編輯的控件的屬性,如 TextBox 的 Text 屬性和 CheckBox 的 IsChecked 屬性)默認為 TwoWay 綁定。確定依賴項屬性綁定在默認情況下是單向還是雙向的編程方法是:使用 GetMetadata 獲取屬性的屬性元數據,然后檢查 BindsTwoWayByDefault 屬性的布爾值。
-
OneWayToSource 與 OneWay 綁定相反;它在目標屬性更改時更新源屬性。一個示例方案是您只需要從 UI 重新計算源值的情況。
-
OneTime綁定 ,該綁定會導致源屬性初始化目標屬性,但不傳播后續更改。這意味著,如果數據上下文發生了更改,或者數據上下文中的對象發生了更改,則更改會反映在目標屬性中。如果您使用的數據的當前狀態的快照適于使用,或者這些數據是真正靜態的,則適合使用此綁定類型。如果要使用源屬性中的某個值初始化目標屬性,并且事先不知道數據上下文,則也可以使用此綁定類型。此綁定類型實質上是 OneWay 綁定的簡化形式,在源值不更改的情況下可以提供更好的性能。
每個依賴項屬性的默認值都不同。一般情況下,用戶可編輯控件屬性(例如文本框和復選框的屬性)默認為雙向綁定,而多數其他屬性默認為單向綁定。確定依賴項屬性綁定在默認情況下是單向還是雙向的編程方法是:使用 GetMetadata 來獲取屬性的屬性元數據,然后檢查 BindsTwoWayByDefault 屬性的布爾值。
三、實現數據源更改影響目標更改
如果要實現數據源更改時,改變目標的值(即上圖中的OneWay方式及TwoWay方式的由綁定源到綁定目標方向的數據綁定),需使數據源對象實現System.ComponentModel命名空間的INotifyPropertyChanged接口。INotifyPropertyChanged接口中定義了一個PropertyChanged事件,在某屬性值發生變化時引發此事件,即可通知綁定目標更改其顯示的值。例如:
1: using System.ComponentModel; 2: 3: namespace BasicWPFDataBinding 4: { 5: public class MyData : INotifyPropertyChanged 6: { 7: #region INotifyPropertyChanged Members 8: public event PropertyChangedEventHandler PropertyChanged; 9: #endregion 10: 11: public MyData() 12: { 13: Name = "Tom"; 14: } 15: 16: private string _Name; 17: public string Name 18: { 19: set 20: { 21: _Name = value; 22: 23: if (PropertyChanged != null) 24: { 25: // 引發PropertyChanged事件, 26: // PropertyChangedEventArgs構造方法中的參數字符串表示屬性名 27: PropertyChanged(this,new PropertyChangedEventArgs("Name")); 28: } 29: } 30: get 31: { 32: return _Name; 33: } 34: } 35: } 36: }?
四、實現綁定目標的值更改影響綁定源的值
若實現實現綁定目標的值更改影響綁定源的值(即上圖中TwoWay的由綁定目標到綁定源方向,及OneWayToSource),可以設置相應控件綁定時的UpdateSourceTrigger的值,其值有三種:
- PropertyChanged:當綁定目標屬性更改時,立即更新綁定源。
- LostFocus:當綁定目標元素失去焦點時,更新綁定源。
- Explicit:僅在調用 UpdateSource 方法時更新綁定源。
多數依賴項屬性的UpdateSourceTrigger 值的默認值為 PropertyChanged,而 Text 屬性的默認值為 LostFocus。
例如:
1: <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />五、示例:
下面的示例使用第3節中的MyData類作為數據源,演示基于4種綁定方式的執行效果:
XAML代碼如下:
1: <Window x:Class="BasicWPFDataBinding.WinBasicBinding" 2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4: xmlns:c="clr-namespace:BasicWPFDataBinding" 5: Title="WinBasicBinding" Height="360" Width="360"> 6: <Grid> 7: <Grid.ColumnDefinitions> 8: <ColumnDefinition/> 9: <ColumnDefinition/> 10: </Grid.ColumnDefinitions> 11: <Grid.RowDefinitions> 12: <RowDefinition/> 13: <RowDefinition/> 14: </Grid.RowDefinitions> 15: <StackPanel Grid.Row="0" Grid.Column="0" x:Name="panelOneTime"> 16: <StackPanel.Resources> 17: <c:MyData x:Key="myDataSourceA" /> 18: </StackPanel.Resources> 19: <StackPanel.DataContext> 20: <Binding Source="{StaticResource myDataSourceA}" /> 21: </StackPanel.DataContext> 22: <TextBlock Text="OneTime Binding" /> 23: <TextBox Margin="5" Text="{Binding Path=Name, Mode=OneTime}" /> 24: <Button Margin="5" Content="Change Name" 25: x:Name="btnOneTimeBindingChange" Click="btnOneTimeBindingChange_Click" /> 26: <Button Margin="5" Content="Get Name" 27: x:Name="btnOnTimeBindingGet" Click="btnOnTimeBindingGet_Click" /> 28: </StackPanel> 29: <StackPanel Grid.Row="0" Grid.Column="1" x:Name="panelOneWay"> 30: <StackPanel.Resources> 31: <c:MyData x:Key="myDataSourceB" /> 32: </StackPanel.Resources> 33: <StackPanel.DataContext> 34: <Binding Source="{StaticResource myDataSourceB}" /> 35: </StackPanel.DataContext> 36: <TextBlock Text="OneWay Binding" /> 37: <TextBox Margin="5" 38: Text="{Binding Path=Name, Mode=OneWay}" /> 39: <Button Margin="5" Content="Change Name" 40: x:Name="btnOneWayeBindingChange" Click="btnOneWayeBindingChange_Click" /> 41: <Button Margin="5" Content="Get Name" 42: x:Name="btnOneWayBindingGet" Click="btnOneWayBindingGet_Click" /> 43: </StackPanel> 44: <StackPanel Grid.Row="1" Grid.Column="0" x:Name="panelTwoWay"> 45: <StackPanel.Resources> 46: <c:MyData x:Key="myDataSourceC" /> 47: </StackPanel.Resources> 48: <StackPanel.DataContext> 49: <Binding Source="{StaticResource myDataSourceC}" /> 50: </StackPanel.DataContext> 51: <TextBlock Text="TwoWay Binding" /> 52: <TextBox Margin="5" 53: Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 54: <Button Margin="5" Content="Change Name" 55: x:Name="btnTwoWayBindingChange" Click="btnTwoWayBindingChange_Click" /> 56: <Button Margin="5" Content="Get Name" 57: x:Name="btnTwoWayBindingGet" Click="btnTwoWayBindingGet_Click" /> 58: <TextBlock Margin="5" 59: Text="{Binding Path=Name, Mode=OneWay}" /> 60: </StackPanel> 61: <StackPanel Grid.Row="1" Grid.Column="1" x:Name="panelOneWayToSource"> 62: <StackPanel.Resources> 63: <c:MyData x:Key="myDataSourceD" /> 64: </StackPanel.Resources> 65: <StackPanel.DataContext> 66: <Binding Source="{StaticResource myDataSourceD}" /> 67: </StackPanel.DataContext> 68: <TextBlock Text="OneWayToSource Binding" /> 69: <TextBox Margin="5" 70: Text="{Binding Path=Name, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" /> 71: <Button Margin="5" Content="Change Name" 72: x:Name="btnOneWayToSourceBindingChange" Click="btnOneWayToSourceBindingChange_Click" /> 73: <Button Margin="5" Content="Get Name" 74: x:Name="btnOneWayToSourceBindingGet" Click="btnOneWayToSourceBindingGet_Click" /> 75: <TextBlock Margin="5" 76: Text="{Binding Path=Name, Mode=OneWay}" /> 77: </StackPanel> 78: </Grid> 79: </Window>代碼文件如下:
1: using System.Windows; 2: 3: namespace BasicWPFDataBinding 4: { 5: /// <summary> 6: /// Interaction logic for WinBasicBinding.xaml 7: /// </summary> 8: public partial class WinBasicBinding : Window 9: { 10: public WinBasicBinding() 11: { 12: InitializeComponent(); 13: } 14: 15: #region OneTime綁定 16: private void btnOneTimeBindingChange_Click(object sender, RoutedEventArgs e) 17: { 18: MyData source = (MyData)(panelOneTime.DataContext); 19: source.Name = "Jerry"; 20: 21: MessageBox.Show( 22: "myData.Name has been changed to Jerry", 23: "System Information", 24: MessageBoxButton.OK, 25: MessageBoxImage.Information); 26: } 27: 28: private void btnOnTimeBindingGet_Click(object sender, RoutedEventArgs e) 29: { 30: MyData source = (MyData)(panelOneTime.DataContext); 31: 32: string name = source.Name; 33: 34: MessageBox.Show( 35: string.Format("myData.Name value is {0}.", name), 36: "System Information", 37: MessageBoxButton.OK, 38: MessageBoxImage.Information); 39: } 40: #endregion 41: 42: #region OneWay綁定 43: private void btnOneWayeBindingChange_Click(object sender, RoutedEventArgs e) 44: { 45: MyData source = (MyData)(panelOneWay.DataContext); 46: source.Name = "Jerry"; 47: 48: MessageBox.Show( 49: "myData.Name has been changed to Jerry", 50: "System Information", 51: MessageBoxButton.OK, 52: MessageBoxImage.Information); 53: } 54: 55: private void btnOneWayBindingGet_Click(object sender, RoutedEventArgs e) 56: { 57: MyData source = (MyData)(panelOneWay.DataContext); 58: 59: string name = source.Name; 60: 61: MessageBox.Show( 62: string.Format("myData.Name value is {0}.", name), 63: "System Information", 64: MessageBoxButton.OK, 65: MessageBoxImage.Information); 66: } 67: #endregion 68: 69: #region TwoWay綁定 70: private void btnTwoWayBindingChange_Click(object sender, RoutedEventArgs e) 71: { 72: MyData source = (MyData)(panelTwoWay.DataContext); 73: source.Name = "Jerry"; 74: 75: MessageBox.Show( 76: "myData.Name has been changed to Jerry", 77: "System Information", 78: MessageBoxButton.OK, 79: MessageBoxImage.Information); 80: } 81: 82: private void btnTwoWayBindingGet_Click(object sender, RoutedEventArgs e) 83: { 84: MyData source = (MyData)(panelTwoWay.DataContext); 85: 86: string name = source.Name; 87: 88: MessageBox.Show( 89: string.Format("myData.Name value is {0}.", name), 90: "System Information", 91: MessageBoxButton.OK, 92: MessageBoxImage.Information); 93: } 94: #endregion 95: 96: #region OneWayToSource綁定 97: private void btnOneWayToSourceBindingChange_Click(object sender, RoutedEventArgs e) 98: { 99: MyData source = (MyData)(panelOneWayToSource.DataContext); 100: source.Name = "Jerry"; 101: 102: MessageBox.Show( 103: "myData.Name has been changed to Jerry", 104: "System Information", 105: MessageBoxButton.OK, 106: MessageBoxImage.Information); 107: } 108: 109: private void btnOneWayToSourceBindingGet_Click(object sender, RoutedEventArgs e) 110: { 111: MyData source = (MyData)(panelOneWayToSource.DataContext); 112: 113: string name = source.Name; 114: 115: MessageBox.Show( 116: string.Format("myData.Name value is {0}.", name), 117: "System Information", 118: MessageBoxButton.OK, 119: MessageBoxImage.Information); 120: } 121: #endregion 122: } 123: }程序執行,我們可以得到如下的結論:
- 對于OneTime綁定:在界面中顯示的為數據源的初始值,更改數據源的值的時候,不會更改界面的數據顯示;更改界面的數據也不會影響到數據源的數據。
- 對于OneWay綁定:在界面中顯示的數據可以隨數據源的值的變化而變化,但更改界面的數據不會影響到數據源。
- 對于TwoWay綁定:界面中顯示的數據及數據源的數據可以雙向顯示及更新。
- 對于OneWayToSource綁定:初始時界面的數據為空;更改界面的數據可以影響數據源的值,但是更改數據源的值不會體現在界面上。
轉載于:https://www.cnblogs.com/J-FoX/archive/2012/06/07/2539992.html
總結
以上是生活随笔為你收集整理的WPF and Silverlight 学习笔记(二十):WPF数据绑定概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 存储知识学习笔记
- 下一篇: 小白学数据分析-----从购买记录分析道