七,WPF的元素绑定
- 数据绑定是一种关系,该关系告诉WPF从一个源对象提取一些信息,并使用这些信息设置目标对象的属性,目标属性总是依赖项属性,然而,源对象可以是任何内容。
- 源对象是WPF元素并且源属性是依赖项属性的数据绑定,这是最简单的数据绑定。
绑定表达式
如下XAML示例,数据绑定表达式使用XAML扩展标记,因为绑定表达式以Binding开头,所以它实际上是创建了一个System.Windows.Data.Binding类实例,且设置了它的两个属性:ElementName属性(指示源元素)和Path属性(指示源元素中的属性)。
<Window x:Class="WpfApplication1.Test2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Test2" Height="600" Width="600"> <Grid> <StackPanel> <Slider Name="sliderFontSize" Margin="3" Minimum="1" Maximum="40" Value="10" TickPlacement="TopLeft" /> <TextBlock Margin="10" Text="Simple Text" FontSize="{Binding ElementName=sliderFontSize,Path=Value,Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Center" /> </StackPanel> </Grid> </Window>
也可以使用代码进行数据绑定,以下代码完成和以上代码相同的绑定:
Binding binding = new Binding(); binding.Source = sliderFontSize; binding.Path = new PropertyPath("Value"); binding.Mode = BindingMode.TwoWay; txtBTest.SetBinding(TextBlock.FontSizeProperty, binding);
绑定更新
当使用OneWay或TwoWay绑定时,改变后的值会立即从源传播到目标,而从目标到源,未必会立即发生,它们的行为由Binding.UpdateSourceTrigger属性控制:
我们可以在代码中使用BindingExpression.UpdateSource()方法来完全控制源对象的更新时机,此时必须选择UpdateSourceTrigger.Explicit模式,为了获取BindingExpression对象,需要调用GetBindingExpression()方法,并传入具有绑定的目标属性,每个元素都从FrameworkElement基类继承了该方法, -
源对象是非元素对象的数据绑定
当绑定到一个非元素对象时,就需要放弃Binding.ElementName属性,并使用以下属性中的一个:
Source
此属性非常简单,唯一的问题是为了进行绑定,需要具有数据对象。我们可以从资源中提取数据对象,可以通过编码生成数据对象,也可以在数据提供程序的帮助下获取数据对象。最简单的选项是将Source属性指向一些已经准备好了的静态对象。例如:<TextBlock Margin="5" Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=LineSpacing}"></TextBlock>
另一种选项是绑定到一个先前作为资源创建的对象,例如下面的标记创建一个指向Calibri字体的FontFamily对象:
<Window.Resources> <FontFamily x:Key="CustomFont">Calibri</FontFamily> </Window.Resources> <TextBlock Margin="5" Text="{Binding Source={StaticResource CustomFont}, Path=Source}"></TextBlock>
RelativeSource
通过此属性可以根据相对于目标对象的关系指向源对象。例如,可以将一个元素绑定到自身或绑定到父元素。为了设置RelativeSource属性,需要使用RelativeSource对象。这会使语法变的更加复杂,因为除了需要创建一个Binding对象外,还需要创建一个嵌套的RelativeSource对象。有两种方法来进行设置,属性设置语法和标记扩展,如下所示:<TextBlock Margin="10"> <TextBlock.Text> <Binding Path="Title"> <Binding.RelativeSource> <RelativeSource Mode="FindAncestor" AncestorType="{x:Type Window}"/> </Binding.RelativeSource> </Binding> </TextBlock.Text> </TextBlock>
<TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"></TextBlock>
DataContext
如果没有使用Source或RelativeSource属性指向一个源,WPF就从当前元素开始在元素树中向上查找,检查每个元素的DataContext属性,并使用第一个非空的DataContext属性。可以使用和设置Source属性相同的方法设置元素的DataContext属性,也就是说,可以提供内联对象,从一个静态属性中提取,或者从一个资源中提取。示例如下:<StackPanel Margin="10" DataContext="{x:Static SystemFonts.IconFontFamily}"> <TextBlock Margin="5" Text="{Binding Path=Source}"></TextBlock> <TextBlock Margin="5" Text="{Binding Path=LineSpacing}"></TextBlock> <TextBlock Margin="5" Text="{Binding Path=FamilyTypefaces[0].Style}"></TextBlock> <TextBlock Margin="5" Text="{Binding Path=FamilyTypefaces[0].Weight}"></TextBlock> </StackPanel>