转:WPF and Silverlight 学习笔记(二十):WPF数据绑定概述

refer to: http://tech.ddvip.com/2009-05/1241599368117968.html

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 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
1: <TextBox Text= "{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  />

  五、示例:

  下面的示例使用第3节中的MyData类作为数据源,演示基于4种绑定方式的执行效果:

  XAML代码如下:

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
 1: <Window x:Class= "BasicWPFDataBinding.WinBasicBinding"
 
 
 
 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
 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绑定:初始时界面的数据为空;更改界面的数据可以影响数据源的值,但是更改数据源的值不会体现在界面上。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值