WPF 元素绑定

白昼怎懂夜的黑 提交于 2021-02-15 11:07:17

简单来说,数据绑定是一种关系,最简单的关系就是 源对象是WPF元素而且源属性是依赖项属性

 绑定表达式

当使用数据绑定时,不必对源对象(如Slider控件)做任何改动,只需要配置源对象使其属性具有正确的值范围

<Slider Name="SliderFontSize"
        Margin="3"
        Minimum="1"
        Maximum="40"
        Value="10"
        TickFrequency="1"
        TickPlacement="TopLeft">
</Slider>
<TextBlock Margin="10,38,10,-18"
           Text="Simple Text"
           Name="lblSampleText"
           FontSize="{Binding ElementName=SliderFontSize,Path=Value}">

</TextBlock>

数据绑定表达式使用XAML标记扩展,以单词Binding开头,以上的代码设置了两个属性:ElementName属性(指示源元素)和Path属性(源元素中的属性)

之所以使用名称Path,是因为Path可能指向属性的属性(FontFamily.Source)也可能是指向属性使用的索引器(Content.Children[0])。可构建具有多层次的路径,使其指向属性的属性的属性。

绑定错误

WPF不会引发异常,但会出现类似于:

绑定模式

 

 单击Set to Large按钮时,会运行下面的代码

private void Button_Click(object sender, RoutedEventArgs e){
            SliderFontSize.Value = 30;
 }

效果会通过数据绑定强制改变字体尺寸。效果与移动滑动条上的滑块一样

而下面的代码却无法达到正常的效果,破坏了绑定,滑块无法对字体做出改变。

private void Button_Click(object sender, RoutedEventArgs e){
            lblSampleText.FontSize = 30;
}

可以使用一种方式,强制在两个方向传递数值:从源到目标以及从目标到源。

<TextBlock Margin="40"
   Text="Simple Text"
   Name="lblSampleText"
   Width="300"
   Height="100"
   FontSize="{Binding ElementName=SliderFontSize,Path=Value,Mode=TwoWay}">

目前还不要考虑使用双向绑定。

但设置Binding.Mode属性时,WPF有5个

对于几种模式,如下图

OneWayToSource

和OneWay的区别,是绑定表达式的放置位置

OneWayToSource模式允许通过在通常被视为绑定源的对象中放置表达式,从而翻转源和目标。

使用这个方式常见的原因是设置非依赖项模式(绑定表达式只能用于依赖项模式),但通过这个模式可以克服这个箱子,但前提是提供数值的属性本身是依赖项属性

Default

WPF使用了一种不同的,默认情况下依赖于所绑定属性的模式(每一个依赖项属性都有一个元数据 FrameworkPropertyMetadata.BindsTwoWayByDefault标志,该标志指示属性是使用单项绑定还是双向绑定)

使用代码创建绑定

还可以使用BindingOperation类的两个静态方法移除绑定。ClearBinding()方法使用依赖项属性(该属性具有希望删除的绑定)的引用作为参数。而ClearAllBindins()方法为元素删除所有数据绑定

在一些特殊的情况下,会希望使用代码创建绑定

使用代码检索绑定

可使用代码检索绑定并检查其属性,而不必考虑绑定最初是用代码还是标记创建的

可采用两种方式来获取绑定信息。第一种方式是使用静态方法BindingOperations.GetBinding来检索相应的Binding对象。这需要提供两个参数:绑定元素以及具有绑定表达式的属性

一旦拥有绑定对象,就可以检查其属性。绑定元素名Binding.ElementName提供了表达式的值(这里是sliderFontSize),Binding.Path提供了PropertyPath对象从绑定对象提取绑定值,Binding.Path.Path获取绑定属性的名称(这里是Value)。还有Binding.Mode属性,用于告知绑定何时更新元素。

WPF还允许通过调用BindingOperations.GetBingingExpression方法获得更实用的BindingExpression对象。

BindingExpression对象包括一些属性,用于复制Bingding对象提供的信息。

 多绑定

希望目标属性受多个源的影响,比如,如果希望使用两个相等的合法绑定来设置属性(创建绑定时,只能指定一个目标属性),可使用多种方法突破这一限制。

最简单的方法是更改数据绑定模式,Mode属性允许改变绑定方向,(双向绑定),可使用这项技术创建多个设置同一属性的绑定表达式。

对滑动条实例的一个变体,添加一个能设置精确字体尺寸的文本框。可以使用文本框和滑块设置字体。

尽管不能再为FontSize属性添加另外一个绑定,但可以将新控件TextBox绑定到TextBlock.FontSize属性

<TextBox HorizontalAlignment="Left"
                 Height="23"
                 Margin="240,304,0,0"
                 TextWrapping="Wrap"
                 Text="{Binding ElementName=lblSampleText,Path=FontSize,Mode=TwoWay}"
                 VerticalAlignment="Top"
                 Width="120" />

Slider.Value属性是双精度类型,将TickFrequency属性设置为1,将IsSnapToTick属性设置为true

直到文本框失去焦点,才会应用文本框中的改变。如果不希望这么做,可以使用Bindind对象的UpdateSourceTrigger属性立即更新

注意,如果使用textbox去绑定滑块,则是立即更新

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Slider Name="SliderFontSize"
                Margin="3"
                Minimum="1"
                Maximum="40"
                Value="{Binding ElementName=txt,Path=Text}"
                TickFrequency="1"
                TickPlacement="TopLeft">
        </Slider>
        <TextBlock Margin="40"
                   Text="Simple Text"
                   Name="lblSampleText"
                   Width="300"
                   Height="100"
                   FontSize="{Binding ElementName=SliderFontSize,Path=Value,Mode=TwoWay}">

        </TextBlock>
        <Button Content="Set to Large"
                HorizontalAlignment="Left"
                Margin="608,279,0,0"
                VerticalAlignment="Top"
                Width="75" 
                Click="Button_Click"/>
        <TextBox HorizontalAlignment="Left"
                 Height="23"
                 Margin="240,304,0,0"
                 TextWrapping="Wrap"
                 Text="10"
                 VerticalAlignment="Top"
                 Width="120" 
                 x:Name="txt"/>
    </Grid>
</Window>

绑定更新

为什么以上两种绑定更新的时间不同?

当使用OneWay或TwoWay绑定时,改变后的值会立即从源传播到目标。当反向传递时,从目标到源,未必会立即发送。

它们的行为Binding.UpdateSourceTrigger属性控制,

<TextBox HorizontalAlignment="Left"
                 Height="23"
                 Margin="240,304,0,0"
                 TextWrapping="Wrap"
                 Text="{Binding ElementName=lblSampleText,Path=FontSize,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                 VerticalAlignment="Top"
                 Width="120" />

要完全控制对象的更新时机,可选择Explicit模式,此时由你的代码手动更新。

可添加Apply按钮,调用BindingExpression.UpdateSouce方法,触发立即刷新行为

当然在使用BindingExpression之前,我们需要一个类来获取。

BindingExpression对象包括:

为了获取BindingExpression对象,需要使用GetBindingExpression方法,并传入具有绑定的目标属性

绑定延迟

可以使用Binding对象的Delay属性

绑定到非元素对象

当绑定到非元素对象时,需要放弃Binding.ElementName属性,并使用以下属性中的一个:

 Source属性

source为了数据绑定,需要具有数据对象。

可使用几种方法获取数据对象。可从资源中提取数据对象,可通过编写代码生成数据对象,也可在数据提供的程序的帮助下获取数据对象。

这个绑定表达式获取由静态属性SystemFonts.IconFontFamily提供的FontFamily对象,然后将Binding.Path属性设置为FontFamily.Source属性。

RelativeSource

通过RelativeSource属性可根据相对于目标对象的关系指向源对象。可使用RelativeSource属性将元素绑定到自身或父元素

为设置Bind.RelativeSource属性,需要使用RelativeSource对象,这样需要多创建一个RelativeSource对象。

<TextBlock>
    <TextBlock.Text>
        <Binding Path="Title">
            <Binding.RelativeSource>
                <RelativeSource Mode="FindAncestor"
                                AncestorType="{x:Type Window}">
                </RelativeSource>
             </Binding.RelativeSource>
        </Binding>
    </TextBlock.Text>
</TextBlock>
FindAncestor模式。告知查找元素树知道发现AncestorType属性定义的元素模式

 更常用的方法是使用Binding和RelativeSource标记扩展

<TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}}"></TextBlock>

并不总是可以使用Source或ElementNmae,因为源对象和目标对象在不同的标记块中。

DataContext属性

在某些情况下,会将大量的元素绑定到同一个对象。

可以在StackPanel里面设置绑定

当绑定表达式中省略信息时,WPF会检查元素的DataContext属性。如果属性为null,WPF会继续向上查找不为null的数据上下文。如果找到了一个数据上下文,就为绑定使用找到的数据上下文,没有找到就不设置。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!