【WPF】数据绑定

什么是数据绑定?

数据绑定是在应用 UI 与其显示的数据之间建立连接的过程。 如果绑定具有正确的设置,并且数据提供适当的通知,则在数据更改其值时,绑定到该数据的元素会自动反映更改。 数据绑定还意味着,如果元素中数据的外部表示形式发生更改,则基础数据可以自动进行更新以反映更改。 例如,如果用户编辑 TextBox 元素中的值,则基础数据值会自动更新以反映该更改。

数据绑定基本概念

不论要绑定什么元素,也不论数据源是什么性质,每个绑定都始终遵循下图所示的模型。
在这里插入图片描述

通常情况下,每个绑定具有四个组件:

  • 绑定目标对象。
  • 目标属性。
  • 绑定源。
  • 指向绑定源中要使用的值的路径。

例如,如果要将 TextBox 的内容绑定到 Employee.Name 属性,则目标对象是 TextBox,目标属性是 Text属性,要使用的值是 Name,源对象是 Employee 对象。

数据流的方向

可以通过设置 Binding.Mode 来控制数据流。
在这里插入图片描述

  • OneWay

通过 OneWay绑定,对源属性的更改会自动更新目标属性,但对目标属性的更改不会传播回源属性。 如果绑定的控件为隐式只读,则此类型的绑定适用。 例如,可能会绑定到股票行情自动收录器这样的源,也可能目标属性没有用于进行更改的控件接口(例如表的数据绑定背景色)。 如果无需监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的系统开销。

  • TwoWay

通过 TwoWay 绑定,更改源属性或目标属性时会自动更新另一方。 此类型的绑定适用于可编辑窗体或其他完全交互式 UI 方案。 大多数属性默认为 OneWay 绑定,但某些依赖属性通常 (用户可编辑控件的属性,例如 TextBox.Text 和 CheckBox.IsChecked) 默认为 TwoWay 绑定。 用于确定依赖属性绑定在默认情况下是单向还是双向的编程方法是:使用 DependencyProperty.GetMetadata 获取属性元数据,然后检查 FrameworkPropertyMetadata.BindsTwoWayByDefault 属性的布尔值。

  • OneWayToSource

OneWayToSource 绑定与 OneWay 绑定相反;当目标属性更改时,它会更新源属性。 一个示例方案是只需要从 UI 重新计算源值的情况。

  • OneTime

OneTime 绑定未在图中显示,该绑定会使源属性初始化目标属性,但不传播后续更改。 如果数据上下文发生更改,或者数据上下文中的对象发生更改,则更改不会在目标属性中反映。 如果适合使用当前状态的快照或数据实际为静态数据,则此类型的绑定适合。 如果你想使用源属性中的某个值来初始化目标属性,且提前不知道数据上下文,则此类型的绑定也有用。 此模式实质上是 OneWay 绑定的一种简化形式,它在源值不更改的情况下提供更好的性能。

若要检测源更改(适用于 OneWay 和 TwoWay 绑定),则源必须实现合适的属性更改通知机制,例如 INotifyPropertyChanged。

触发源更新的因素

TwoWayOneWayToSource 绑定侦听目标属性中的更改,并将更改传播回源(称为更新源)。 例如,可以编辑文本框的文本以更改基础源值。
但是,在编辑文本时或完成文本编辑后控件失去焦点时,源值是否会更新?
Binding.UpdateSourceTrigger 属性确定触发源更新的因素。 下图中右箭头的点说明了 Binding.UpdateSourceTrigger 属性的角色。
在这里插入图片描述
如果 UpdateSourceTrigger 值为 UpdateSourceTrigger.PropertyChanged,则目标属性更改后,TwoWay 或 OneWayToSource 绑定的右箭头指向的值会立即更新。 但是,如果 UpdateSourceTrigger 值为 LostFocus,则仅当目标属性失去焦点时才会使用新值更新该值。

与 Mode 属性类似,不同的依赖属性具有不同的默认 UpdateSourceTrigger 值。 大多数依赖属性的默认值为 PropertyChanged,而 TextBox.Text 属性的默认值为 LostFocus。 PropertyChanged 表示源更新通常在每次目标属性更改时发生。 即时更改适用于 CheckBox 和其他简单控件。 但对于文本字段,每次击键后都进行更新会降低性能,用户也没有机会在提交新值之前使用 Backspace 键修改键入错误。

创建绑定

使用 Binding 对象建立绑定,且每个绑定通常具有四个组件:绑定目标、目标属性、绑定源以及指向要使用的源值的路径。
示例,绑定源对象是一个名为 MyData 的类,该类在 SDKSample 命名空间中定义。 出于演示目的,MyData 具有名为 ColorName 的字符串属性,其值设置为“Red”。 因此,此示例生成一个具有红色背景的按钮。

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:c="clr-namespace:SDKSample">
    <DockPanel.Resources>
        <c:MyData x:Key="myDataSource"/>
    </DockPanel.Resources>
    <DockPanel.DataContext>
        <Binding Source="{StaticResource myDataSource}"/>
    </DockPanel.DataContext>
    <Button Background="{Binding Path=ColorName}"
            Width="150" Height="30">
        I am bound to be RED!
    </Button>
</DockPanel>

ColorName 属性的类型为字符串而 Background 属性的类型为 Brush。,此绑定使用默认类型转换。通过设置 DockPanel.DataContext 属性指定绑定源。 然后,Button 从其父元素 DockPanel 继承 DataContext 值。
可通过多种方法指定绑定源对象。 将多个属性绑定到同一个源时,可以使用父元素上的 DataContext 属性。 不过,有时在个别绑定声明中指定绑定源可能更为合适。 对于前面的示例,不使用 DataContext 属性,而是通过在按钮的绑定声明中直接设置 Binding.Source 属性来指定绑定源。

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:c="clr-namespace:SDKSample">
    <DockPanel.Resources>
        <c:MyData x:Key="myDataSource"/>
    </DockPanel.Resources>
    <Button Background="{Binding Source={StaticResource myDataSource}, Path=ColorName}"
            Width="150" Height="30">
        I am bound to be RED!
    </Button>
</DockPanel>

除直接在元素中设置 DataContext 属性、从上级元素(例如第一个示例中的按钮)继承 DataContext 值以及通过在绑定上设置 Binding.Source 属性(例如最后一个示例中的按钮)来显式指定绑定源外,你还可以使用 Binding.ElementName 属性或 Binding.RelativeSource 属性指定绑定源。 当绑定到应用中的其他元素时(例如,使用滑块调整按钮的宽度时),ElementName 属性非常有用。 在 ControlTemplate 或 Style 中指定绑定时,可以使用 RelativeSource 属性。

如果绑定源是一个对象,则使用 Binding.Path 属性指定要用于绑定的值。 如果要绑定到 XML 数据,则使用 Binding.XPath 属性指定值。 在某些情况下,使用 Path 属性(即使数据为 XML)可能更为合适。 例如,如果要访问返回的 XmlNode(作为 XPath 查询的结果)的 Name 属性,则除 XPath 属性外,还应使用 Path 属性。

但在要绑定到整个对象的方案中,要使用的值会与绑定源对象相同。 在这些情况下,可以不指定 Path。

<ListBox ItemsSource="{Binding}"
         IsSynchronizedWithCurrentItem="true"/>

以上示例使用空绑定语法:{Binding}。 在此示例中,ListBox 从父 DockPanel 元素继承 DataContext(此示例中未显示)。 未指定路径时,默认为绑定到整个对象。 换句话说,此示例中的路径已省略,因为要将 ItemsSource 属性绑定到整个对象。
除了绑定到集合以外,在希望绑定到整个对象,而不是仅绑定到对象的单个属性时,也可以使用此方案。 例如,如果源对象的类型为 String,则可能仅希望绑定到字符串本身。 另一种常见情况是希望将一个元素绑定到一个具有多个属性的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值