数据绑定概述 (WPF .NET)
在这篇文章中
1.什么是数据绑定
2.基本数据绑定概念
3.数据绑定示例
4.创建绑定
Windows Presentation Foundation (WPF) 中的数据绑定为应用提供了一种简单且一致的方式来呈现数据并与之交互。元素可以以 .NET 对象和 XML 的形式绑定到来自不同类型数据源的数据。任何 ContentControl(如Button)和任何 ItemControl(如ListBox或者ListView)都具有内置功能,可灵活设置单个数据项或数据项集合的样式。可以在数据之上生成排序、筛选和分组视图。
与传统模型相比,WPF 中的数据绑定具有多个优点,包括通过广泛的属性对数据绑定的固有支持、灵活的数据 UI 表示形式以及业务逻辑与 UI 的干净分离。
本文首先讨论 WPF 数据绑定的基本概念,然后介绍Binding类的用法和数据绑定的其他功能。
重要
.NET 7 和 .NET 6 的桌面指南文档正在构建中。
什么是数据绑定?
数据绑定是在应用 UI 与其显示的数据之间建立连接的过程。如果绑定具有正确的设置,并且数据提供了正确的通知,则当数据更改其值时,绑定到数据的元素会自动反映更改。数据绑定还意味着,如果元素中数据的外部表示形式发生更改,则可以自动更新基础数据以反映更改。例如,如果用户编辑元素中的值,则基础数据值会自动更新以反映该更改。TextBox
数据绑定的典型用途是将服务器或本地配置数据放入窗体或其他 UI 控件中。在 WPF 中,此概念已扩展为包括将各种属性绑定到不同类型的数据源。在 WPF 中,元素的依赖项属性可以绑定到 .NET 对象(包括 ADO.NET 对象或与 Web 服务和 Web 属性关联的对象)和 XML 数据。
基本数据绑定概念
无论绑定的元素和数据源的性质如何,每个绑定始终遵循下图所示的模型。
如图所示,数据绑定实质上是绑定目标和绑定源之间的桥梁。该图演示了以下基本的 WPF 数据绑定概念:
-
通常,每个绑定都有四个组件:
- 绑定目标对象。
- 目标属性。
- 绑定源。
- 绑定源中要使用的值的路径。
例如,如果将 a 的内容绑定到属性,则可以如下表所示设置绑定:
TextBox
Employee.Name
展开表格 -
目标属性必须是依赖项属性。
大多数 UIElement 属性都是依赖项属性,默认情况下,大多数依赖项属性(只读属性除外)都支持数据绑定。只有派生自 DependencyObject 的类型才能定义依赖项属性。所有 UIElement 类型都派生自 。
DependencyObject
-
绑定源不限于自定义 .NET 对象。
尽管图中未显示,但应注意的是,绑定源对象并不局限于自定义 .NET 对象。WPF 数据绑定支持 .NET 对象、XML 甚至 XAML 元素对象形式的数据。为了提供一些示例,绑定源可以是 UIElement、任何列表对象、ADO.NET 或 Web 服务对象,或者包含 XML 数据的 XmlNode。有关详细信息,请参阅绑定源概述。
请务必记住,在建立绑定时,会将绑定目标绑定到绑定源。例如,如果使用数据绑定在 ListBox 中显示某些基础 XML 数据,则将 Azure 绑定到 XML 数据。ListBox
若要建立绑定,请使用 Binding 对象。本文的其余部分将讨论与对象相关的许多概念以及对象的一些属性和用法。Binding
数据上下文
在 XAML 元素上声明数据绑定时,它们通过查看其直接 DataContext 属性来解析数据绑定。数据上下文通常是绑定源值路径计算的绑定源对象。可以在绑定中重写此行为,并设置特定的绑定源对象值。如果未设置承载绑定的对象的属性,则会检查父元素的属性,依此类推,直到 XAML 对象树的根目录。简而言之,除非在对象上显式设置,否则用于解析绑定的数据上下文是从父级继承的。DataContext
DataContext
可以将绑定配置为使用特定对象进行解析,而不是使用数据上下文进行绑定解析。例如,将一个对象的前景色绑定到另一个对象的背景色时,将直接指定源对象。不需要数据上下文,因为绑定是在这两个对象之间解析的。相反,未绑定到特定源对象的绑定使用数据上下文解析。
当属性更改时,将重新计算可能受数据上下文影响的所有绑定。DataContext
数据流的方向
如上图中的箭头所示,绑定的数据流可以从绑定目标转到绑定源(例如,当用户编辑 a 的值时,源值会更改)和/或从绑定源到绑定目标(例如,如果绑定源提供适当的通知,则会使用绑定源中的更改更新内容)。TextBox
TextBox
你可能希望你的应用使用户能够更改数据并将其传播回源对象。或者,您可能不希望允许用户更新源数据。可以通过设置 Binding.Mode 来控制数据流。
下图说明了不同类型的数据流:
-
OneWay 绑定会导致对源属性的更改自动更新目标属性,但对目标属性的更改不会传播回源属性。如果要绑定的控件是隐式只读的,则此类型的绑定是合适的。例如,您可以绑定到源(如股票行情),或者您的目标属性可能没有提供用于进行更改的控制接口,例如表的数据绑定背景色。如果不需要监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的开销。
-
TwoWay 绑定会导致对源属性或目标属性的更改自动更新另一个属性。这种类型的绑定适用于可编辑窗体或其他完全交互式的 UI 方案。大多数属性默认为 OneWay 绑定,但某些依赖项属性(通常是用户可编辑控件的属性,如 TextBox.Text 和 CheckBox.IsChecked)默认为 TwoWay 绑定。
确定依赖项属性默认是单向绑定还是双向绑定的编程方法是使用 DependencyProperty.GetMetadata 获取属性元数据。此方法的返回类型为 PropertyMetadata,它不包含任何有关绑定的元数据。但是,如果可以将此类型强制转换为派生的 FrameworkPropertyMetadata,则可以检查 FrameworkPropertyMetadata.BindsTwoWayByDefault 属性的布尔值。下面的代码示例演示如何获取 TextBox.Text 属性的元数据:
C#复制public static void PrintMetadata() { // Get the metadata for the property PropertyMetadata metadata = TextBox.TextProperty.GetMetadata(typeof(TextBox)); // Check if metadata type is FrameworkPropertyMetadata if (metadata is FrameworkPropertyMetadata frameworkMetadata) { System.Diagnostics.Debug.WriteLine($"TextBox.Text property metadata:"); System.Diagnostics.Debug.WriteLine($" BindsTwoWayByDefault: {frameworkMetadata.BindsTwoWayByDefault}"); System.Diagnostics.Debug.WriteLine($" IsDataBindingAllowed: {frameworkMetadata.IsDataBindingAllowed}"); System.Diagnostics.Debug.WriteLine($" AffectsArrange: {frameworkMetadata.AffectsArrange}"); System.Diagnostics.Debug.WriteLine($" AffectsMeasure: {frameworkMetadata.AffectsMeasure}"); System.Diagnostics.Debug.WriteLine($" AffectsRender: {frameworkMetadata.AffectsRender}"); System.Diagnostics.Debug.WriteLine($" Inherits: {frameworkMetadata.Inherits}"); } /* Displays: * * TextBox.Text property metadata: * BindsTwoWayByDefault: True * IsDataBindingAllowed: True * AffectsArrange: False * AffectsMeasure: False * AffectsRender: False * Inherits: False */ }
-
OneWayToSource 是 OneWay 绑定的反面;当目标属性发生更改时,它会更新 source 属性。一个示例方案是,如果只需要从 UI 重新计算源值。
-
图中未说明的是 OneTime 绑定,它会导致 source 属性初始化目标属性,但不会传播后续更改。如果数据上下文发生更改或数据上下文中的对象发生更改,则更改不会反映在目标属性中。如果当前状态的快照是合适的,或者数据确实是静态的,则这种类型的绑定是合适的。如果要使用源属性中的某些值初始化目标属性,并且数据上下文事先未知,则这种类型的绑定也很有用。此模式本质上是一种更简单的 OneWay 绑定形式,可在源值不更改的情况下提供更好的性能。
若要检测源更改(适用于 OneWay 和 TwoWay 绑定),源必须实现合适的属性更改通知机制,例如 INotifyPropertyChanged。有关 INotifyPropertyChanged 实现的示例,请参见如何:实现属性更改通知 (.NET Framework)。
Binding.Mode 属性提供有关绑定模式的更多信息,以及如何指定绑定方向的示例。
触发源更新的原因
TwoWay 或 OneWayToSource 绑定侦听目标属性中的更改,并将其传播回源,称为更新源。例如,您可以编辑 TextBox 的文本以更改基础源值。
但是,在编辑文本时或完成文本编辑后,控件失去焦点后,源值是否更新?Binding.UpdateSourceTrigger 属性确定触发源更新的内容。下图中右箭头的点说明了 Binding.UpdateSourceTrigger 属性的作用。
如果该值为 UpdateSourceTrigger.PropertyChanged,则一旦目标属性发生更改,就会更新 TwoWay 或 OneWayToSource 绑定的右箭头指向的值。但是,如果该值为 LostFocus,则仅当目标属性失去焦点时,才会使用新值更新该值。UpdateSourceTrigger
UpdateSourceTrigger
与 Mode 属性类似,不同的依赖项属性具有不同的默认 UpdateSourceTrigger 值。大多数依赖项属性的默认值为 PropertyChanged,这会导致在目标属性值更改时立即更改源属性的值。即时更改适用于 CheckBox 和其他简单控件。但是,对于文本字段,每次击键后更新可能会降低性能,并剥夺用户在提交新值之前退格和修复键入错误的通常机会。例如,该属性默认为 LostFocus 的值,这会导致源值仅在控制元素失去焦点时更改,而不是在属性更改时更改。有关如何查找依赖项属性的默认值的信息,请参阅 UpdateSourceTrigger 属性页。TextBox.Text
UpdateSourceTrigger
TextBox.Text
下表以 TextBox 为例,为每个 UpdateSourceTrigger 值提供了示例方案。
UpdateSourceTrigger 值 | 更新源值时 | TextBox 的示例方案 |
---|---|---|
LostFocus (TextBox.Text 的默认值)) |
当 TextBox 控件失去焦点时。 | 与验证逻辑关联的 TextBox(请参阅下面的数据验证)。 |
PropertyChanged |
在 TextBox 中键入内容时。 | 聊天室窗口中的 TextBox 控件。 |
Explicit |
当应用调用 UpdateSource 时。 | 可编辑窗体中的 TextBox 控件(仅当用户按下提交按钮时才更新源值)。 |
有关示例,请参见如何:控制 TextBox 文本何时更新源 (.NET Framework)。
数据绑定示例
有关数据绑定的示例,请查看数据绑定演示中的以下应用 UI,其中显示了拍卖项的列表。
该应用演示了数据绑定的以下功能:
-
ListBox 的内容绑定到 AuctionItem 对象的集合。AuctionItem 对象具有 Description、StartPrice、StartDate、Category 和 SpecialFeatures 等属性。
-
中显示的数据(AuctionItem 对象)已模板化,以便显示每个项目的描述和当前价格。该模板是使用 DataTemplate 创建的。此外,每个项目的外观取决于所显示的 AuctionItem 的 SpecialFeatures 值。如果 AuctionItem 的 SpecialFeatures 值为 Color,则该项目具有蓝色边框。如果值为 Highlight,则该项目具有橙色边框和星号。“数据模板化”部分提供有关数据模板化的信息。
ListBox
-
用户可以使用提供的数据对数据进行分组、过滤或排序。在上图中,选择了“按类别分组”和“按类别和日期排序”。您可能已经注意到,数据是根据产品的类别分组的,类别名称按字母顺序排列。从图像中很难注意到,但这些项目也按每个类别中的开始日期排序。排序是使用集合视图完成的。绑定到集合部分讨论集合视图。
CheckBoxes
CheckBoxes
-
当用户选择项时,ContentControl 将显示所选项的详细信息。此体验称为“大纲-细节方案”。“大纲方案”部分提供有关此类绑定的信息。
-
StartDate 属性的类型为 DateTime,它返回一个日期,该日期包含毫秒级的时间。在此应用程序中,使用了自定义转换器,以便显示较短的日期字符串。“数据转换”部分提供有关转换器的信息。
当用户选择“添加产品”按钮时,将显示以下窗体。
用户可以编辑表单中的字段,使用简短或详细的预览窗格预览产品列表,并选择添加新的产品列表。任何现有的分组、筛选和排序设置都将应用于新条目。在这种特殊情况下,在上图中输入的项目将显示为“计算机”类别中的第二个项目。Submit
此图中未显示“开始日期”文本框中提供的验证逻辑。如果用户输入的日期无效(格式无效或过去的日期),则用户将收到工具提示和 TextBox 旁边的红色感叹号通知。数据验证部分讨论如何创建验证逻辑。
在介绍上述数据绑定的不同功能之前,我们将首先讨论对理解 WPF 数据绑定至关重要的基本概念。