前面讲依赖项属性的时候说过,依赖项具有内置的更改通知的支持,依赖项属性的一个特性就是数据绑定本章谈谈数据绑定。
简单第说,数据绑定是一种关系, 该关系告诉WPF从源对象提取一些信息,并用这些信息设置目标对象的属性。
目标属性始终是依赖项属性,通常位于WPF元素中—毕竟,WPF数据绑定的最终目标是在用户界面中显示一些信息。然而,源对象可以是任何内容,从另一个WPF元素乃至ADO.NET数据对象或您自行创建的纯数据对象。
下面先说说元素到元素的绑定:
元素到元素的绑定,源对象是WPF元素而且源属性是依赖项属性。
绑定表达式
<Slider x:Name="slider" HorizontalAlignment="Left" Margin="72,38,0,0" VerticalAlignment="Top" Width="223" Value="50" Maximum="100"/> <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="72,83,0,0" TextWrapping="Wrap" Text="Test Text" VerticalAlignment="Top" FontSize="{Binding ElementName=slider,Path=Value}"/>
将Slider滑块的Value值绑定到TextBlock的FontSize上。
数据绑定表达式使用XAML标记扩展,因为正在创建System.Windows.Data.Bingding类的一个实例,所以绑定表达式以单词Bingding开头。尽管可采用多种方式配置Binging对象,但本例中需要设置两个属性:ElementName属性(指示源元素)和Path属性(指示源元素中的属性)
之所以使用名称Path而不是Property,是因为Path可能指向属性的属性(FontFamily.Source),也可能指向属性使用的索引器(如Content.Children[0]).可构建具有多层级层次的路径,使其指向属性的属性的属性。
绑定模式
数据绑定的一个特性是目标会被自动更新,而不考虑源的修改方式。在这个示例中,源只能通过一种方式进行修改——通过用户与滑动条上滑块进行的交互。
添加一个按钮,然后设置字体的大小
private void button_Click(object sender, RoutedEventArgs e) { textBlock.FontSize = 30; }
设置新的字体后,滑动条的位置未相应地更新。且移动滑动条的滑块,文本框的字体大小也不发生改变,说明绑定也失效了。
<Slider x:Name="slider" HorizontalAlignment="Left" Margin="72,38,0,0" VerticalAlignment="Top" Width="223" Value="50" Maximum="100"/> <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="72,83,0,0" TextWrapping="Wrap" Text="Test Text" VerticalAlignment="Top" FontSize="{Binding ElementName=slider,Path=Value,Mode=TwoWay}"/>
将TextBlock的绑定的模式设置为TwoWay,这样上面的字体设置后补也会破坏绑定关系。
绑定的Mode属性可以设置绑定属性的模式,下面列举了Mode的枚举值
1. OneWay
当源属性变化时更新目标属性
2. TwoWay
当源属性变化时更新目标属性,并且当目标属性变化时更新源属性
3. OneTime
最初根据源属性值设置目标属性。然而,其后的所有改变都会被忽略,通常,如果源属性不会变化,可使用这种模式降低开销
4. OneWayToSource
与OneWay类型类似,但方向相反。当目标属性变化时更新源属性,但目标属性永远不会被更新,
此项使用主要用于设置非依赖项属性的属性。前面已经说过,绑定表达式只能用于设置依赖项属性。但通过使用OneWayToSource模式,可克服这一限制.但前提是提供数值的属性本身是依赖项属性。
5. Defalut
此类绑定依赖于目标属性,既可以是双向的(对于用户可以设置的属性,如TextBox.Text属性),也可以是单向的(对于所有其他属性)。除非明确指定了另一种模式。否则所有绑定都使用该方法。
使用代码绑定
bingding.Source = slider; bingding.Path = new PropertyPath("Value"); bingding.Mode = BindingMode.TwoWay;
TextBlock1.SetBinding(TextBlock.FontSizeProperty, bingding);
绑定更新
如果将TextBlx.Text属性绑定到TextBlock.FontSize属性,还存在一个问题。当通过在文本框中输入内容改变显示的字体尺寸时,什么事情也不会发生直到使用Tab键将焦点转移动另一个控件,才会改变。这一行为和在滑动控件中看到的行为不同。滑动条的滑块滑动时会应用新的字体尺寸,而不必使用Tab键转移焦点
这种行为由Bingding.UpdateSourceTrigger属性控制,TextBox的默认用的UpdateSourceTrigger.LostFocus方式从目标向源进行更新的例子。
UpdateSourceTigger枚举值如下:
PropertyChanged: 当目标属性发生变化时立即更新源
LostFocus: 当目标属性发生变化并且目标丢失焦点时更新源
Explict: 除非调用BingdingExpression.UpdateSource()方法,否则无法更新源
Default: 根据目标属性的元数据确定更新行为,大多数属性的默认行为是PropertyChanged,但TextBox.Text属性的默认行为是LostFocus
绑定延迟
在特殊情况下,可使用Bingding对象的Delay属性.等待数毫秒,之后再提交更改
下面是文本框示例的修改版本,会在用户停止输入500毫秒后更新源对象
<TextBlock x:Name="TextBlock1" HorizontalAlignment="Left" Margin="72,83,0,0" TextWrapping="Wrap" Text="Test Text" VerticalAlignment="Top" FontSize="{Binding ElementName=slider,Path=Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=500}"/>