zoukankan      html  css  js  c++  java
  • 数据绑定(Binding)

    Windows Presentation Foundation (WPF) 中的数据绑定为应用程序提供了一种简单、一致的数据表示和交互方法。元素能够以公共语言运行时 (CLR) 对象和 XML 形式绑定到来自各种数据源的数据。

    什么是数据绑定?

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

    基本数据绑定概念

    不论要绑定什么元素,不论数据源的特性是什么,每个绑定都始终遵循下图所示的模型:
    这里写图片描述
    如上图所示,数据绑定实质上是绑定目标与绑定源之间的桥梁。该图演示以下基本的 WPF 数据绑定概念:

    • 通常,每个绑定都具有四个组件:绑定目标对象、目标属性、绑定源,以及要使用的绑定源中的值的路径。例如,如果要将 TextBox 的内容绑定到 Employee 对象的 Name 属性,则目标对象是 TextBox,目标属性是 Text 属性,要使用的值是 Name,源对象是 Employee 对象。
    • 目标属性必须为依赖项属性。大多数 UIElement 属性都是依赖项属性,而大多数依赖项属性(除了只读属性)默认情况下都支持数据绑定。(只有DependencyObject 类型可以定义依赖项属性,所有 UIElement 都派生自 DependencyObject。)
    • 尽管图中并未指出,但应该注意,绑定源对象并不限于自定义 CLR 对象。WPF 数据绑定支持 CLR 对象和 XML 形式的数据。举例来说,绑定源可以是 UIElement、任何列表对象、与 ADO.NET 数据或 Web 服务关联的 CLR 对象,或是包含 XML 数据的 XmlNode。有关更多信息,请参见绑定源概述
      特别注意:当建立绑定时,是将绑定目标绑定到 绑定源。例如,如果要使用数据绑定在一个 ListBox 中显示一些基础 XML 数据,就是将 ListBox 绑定到 XML 数据。

    数据流的方向

    正如上文所述和上图中箭头所示,绑定的数据流可以从数据目标流向数据源(例如,当用户编辑 TextBox 的值时,源值会发生更改)和/或(如果绑定源提供正确的通知)从绑定源流向绑定目标(例如,TextBox 内容会随绑定源中的更改而进行更新)。
    有时可能希望应用程序使用户可以更改数据并将数据传播回源对象。或者,可能不希望允许用户更新源数据。可以通过设置 Binding 对象的 Mode 属性来对此进行控制。下图演示不同类型的数据流:

    这里写图片描述

    • OneWay 绑定导致对源属性的更改会自动更新目标属性,但是对目标属性的更改不会传播回源属性。此绑定类型适用于绑定的控件为隐式只读控件的情况。例如,可能绑定到如股票行情自动收录器这样的源,或许目标属性没有用于进行更改的控件接口(如表的数据绑定背景色)。如果无需监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的系统开销。
    • TwoWay 绑定导致对源属性的更改会自动更新目标属性,而对目标属性的更改也会自动更新源属性。此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。大多数属性都默认为 OneWay 绑定,但是一些依赖项属性(通常为用户可编辑的控件的属性,如 TextBox 的 Text 属性和 CheckBox 的 IsChecked 属性)默认为 TwoWay 绑定。确定依赖项属性绑定在默认情况下是单向还是双向的编程方法是:使用 GetMetadata 获取属性的属性元数据,然后检查 BindsTwoWayByDefault 属性的布尔值。
    • OneWayToSource 与 OneWay 绑定相反;它在目标属性更改时更新源属性。一个示例方案是您只需要从 UI 重新计算源值的情况。
    • OneTime 绑定未在图中显示,该绑定会导致源属性初始化目标属性,但不传播后续更改。这意味着,如果数据上下文发生了更改,或者数据上下文中的对象发生了更改,则更改会反映在目标属性中。如果您使用的数据的当前状态的快照适于使用,或者这些数据是真正静态的,则适合使用此绑定类型。如果要使用源属性中的某个值初始化目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。此绑定类型实质上是 OneWay 绑定的简化形式,在源值不更改的情况下可以提供更好的性能。
      特别注意:若要检测源更改(适用于 OneWay 和 TwoWay 绑定),则源必须实现一种合适的属性更改通知机制(如 INotifyPropertyChanged)。有关 INotifyPropertyChanged 实现的示例,请参见如何:实现属性更改通知

    触发源更新的原因

    TwoWay 或 OneWayToSource 绑定侦听目标属性的更改,并将这些更改传播回源。这称为更新源。例如,可以编辑文本框中的文本以更改基础源值。
    但是,源值是在您编辑文本的同时进行更新,还是在您结束编辑文本并将鼠标指针从文本框移走后才进行更新呢?绑定的 UpdateSourceTrigger 属性确定触发源更新的原因。下图中右箭头的点演示 UpdateSourceTrigger 属性的角色:

    这里写图片描述

    如果 UpdateSourceTrigger 值为 PropertyChanged,则 TwoWay 或 OneWayToSource 绑定的右箭头指向的值会在目标属性更改时立刻进行更新。但是,如果 UpdateSourceTrigger 值为 LostFocus,则仅当目标属性失去焦点时,该值才会使用新值进行更新。
    与 Mode 属性类似,不同的依赖项属性具有不同的默认 UpdateSourceTrigger 值。大多数依赖项属性的默认值都为 PropertyChanged,而 Text 属性的默认值为 LostFocus。这意味着,只要目标属性更改,源更新通常都会发生,这对于 CheckBox 和其他简单控件很有用。但对于文本字段,每次键击之后都进行更新会降低性能,用户也没有机会在提交新值之前使用退格键修改键入错误。这就是为什么 Text 属性的默认值是 LostFocus 而不是 PropertyChanged 的原因。

    创建绑定

    前面几节中讨论的一些概念可以概括为:使用 Binding 对象建立绑定,每个绑定通常都具有四个组件:绑定目标、目标属性、绑定源、要使用的源值的路径。本节讨论如何设置绑定。
    请看下面的示例,其中的绑定源对象是一个名为 MyData 的类,该类在 SDKSample 命名空间中定义。出于演示的目的,MyData 类具有一个名为 ColorName 的字符串属性,该属性的值设置为“Red”。因此,此示例生成一个具有红色背景的按钮。
    C#:

    <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>

    如果将此示例应用于基本关系图,则生成的图如下所示。这是一个 OneWay 绑定,因为 Background 属性在默认情况下支持 OneWay 绑定。

    这里写图片描述

    指定绑定源

    请注意,在上一个示例中,绑定源是通过设置 DockPanel 元素上的 DataContext 属性来指定的。Button 随后从 DockPanel(这是其父元素)继承 DataContext 值。在这里重复一下,绑定源对象是绑定的四个必需组件之一。因此,如果未指定绑定源对象,则绑定将没有任何作用。
    可通过多种方法指定绑定源对象。在将多个属性绑定到相同源时,可以使用父元素上的 DataContext 属性。但是,在各个绑定声明上指定绑定源有时可能更为合适。对于上一个示例,可以不使用 DataContext 属性,而是通过在按钮的绑定声明上直接设置 Source 属性来指定绑定源,如下面的示例中所示:

    <DockPanel.Resources>
      <c:MyData x:Key="myDataSource"/>
    </DockPanel.Resources>
    <Button Width="150" Height="30"
            Background="{Binding Source={StaticResource myDataSource},
                                 Path=ColorName}">I am bound to be RED!</Button>

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

    指定值的路径

    • 如果绑定源是一个对象,则可使用 Path 属性指定要用于绑定的值。如果要绑定到 XML 数据,则可使用 XPath 属性指定该值。在某些情况下,可以使用 Path 属性,即使在数据为 XML 时。例如,如果要访问返回的 XmlNode(作为 XPath 查询的结果)的 Name 属性,则应使用 Path 属性和 XPath 属性。
    • 请注意,虽然我们已强调要使用的值的 Path 是绑定的四个必需组件之一,但在要绑定到整个对象的情况下,要使用的值会与绑定源对象相同。在这些情况下,不指定 Path 比较合适。请看下面的示例:

    C#:

    <ListBox ItemsSource="{Binding}"
             IsSynchronizedWithCurrentItem="true"/>
    • 上面的示例使用空绑定语法:{Binding}。在此情况下,ListBox 从父 DockPanel 元素继承 DataContext(此示例中未演示)。当未指定路径时,默认为绑定到整个对象。换句话说,在此示例中路径已被省略,因为要将 ItemsSource 属性绑定到整个对象。
    • 除了绑定到集合以外,在希望绑定到整个对象,而不是仅绑定到对象的单个属性时,也可以使用此方案。例如,在源对象为类型字符串,并且您仅仅希望绑定到该字符串本身时。

    参考资料:数据绑定概述 https://msdn.microsoft.com/zh-cn/library/ms752347(v=vs.90).aspx

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    vs2010装虚拟机后启动慢
    LINUX FIFO(读书笔记,LINUX程序设计第四版)
    WPF控件 ProgressBar
    C# SQLite操作示列
    win10下使用Linux命令
    类初始化与实例化过程
    结构与类 Delphi
    多线程应用 Delphi
    (珍藏)SQL Server中常用的SQL语句
    获取当前用户本地应用程序设置文件夹 Delphi
  • 原文地址:https://www.cnblogs.com/gongchuangsu/p/4850202.html
Copyright © 2011-2022 走看看