在 Windows 窗体中,不仅可以绑定到传统数据源,还可以绑定到几乎包含数据的任何结构。 可以绑定到在运行时计算的值数组、从文件读取或派生自其他控件的值。
此外,可以将任何控件的任何属性绑定到数据源。 在传统数据绑定中,通常将显示属性(例如 Text 控件的属性 TextBox )绑定到数据源。 使用 .NET,还可以选择通过绑定设置其他属性。 可以使用绑定执行以下任务:
设置图像控件的图形。
设置一个或多个控件的背景色。
设置控件的大小。
从本质上讲,数据绑定是设置窗体上任何控件的运行时可访问属性的自动方式。
与数据绑定相关的接口
ADO.NET 允许你创建许多不同的数据结构,以满足应用程序的绑定需求和正在使用的数据。 你可能想要创建自己的类,用于在 Windows 窗体中提供或使用数据。 这些对象可以提供不同级别的功能和复杂性。 从基本数据绑定,到提供设计时支持、错误检查、变更通知,甚至支持对数据本身所做更改进行结构化回滚。
数据绑定接口的使用者
以下部分介绍两组接口对象。 第一组接口由数据源作者在数据源上实现。 数据源使用者(如 Windows 窗体控件或组件)实现这些接口。 第二组接口旨在由组件作者使用。 组件作者在创建数据绑定组件时使用这些接口,供 Windows 窗体数据绑定引擎使用。 可以在与表单关联的类中实现这些接口,以启用数据绑定。 每个事例都提供一个类,该类实现实现与数据的交互的接口。 Visual Studio 快速应用程序开发(RAD)数据设计体验工具已利用此功能。
供数据源作者实现的接口
Windows 窗体控件实现以下这些接口:
IList 接口
实现接口的IList类可以是、ArrayArrayList或CollectionBase。 这些是类型 Object 项的索引列表,列表必须包含同质类型,因为索引的第一项确定类型。
IList
仅在运行时才可用于绑定。注释
如果要创建用于与 Windows 窗体绑定的业务对象列表,应考虑使用 BindingList<T>。
BindingList
这是一个可扩展类,用于实现双向 Windows 窗体数据绑定所需的主接口。IBindingList 接口
实现接口的 IBindingList 类提供更高级别的数据绑定功能。 此实现提供基本的排序功能和更改通知。 当列表项更改以及列表本身发生更改时,这两者都很有用。 如果计划将多个控件绑定到同一数据,则更改通知非常重要。 它有助于对其中一个控件进行数据更改,以传播到其他绑定控件。
注释
当SupportsChangeNotification属性启用了IBindingList接口的更改通知并且
true
时,会引发ListChanged事件,这表明列表已更改或列表中的某个项已更改。更改的类型由 ListChangedType 参数的属性 ListChangedEventArgs 描述。 因此,每当数据模型更新时,任何依赖视图(如绑定到同一数据源的其他控件)也将更新。 但是,列表中包含的对象在更改时必须通知列表,以便列表可以引发 ListChanged 事件。
注释
BindingList<T> 提供了 IBindingList 接口的泛型实现。
-
实现接口的 IBindingListView 类提供实现 IBindingList的所有功能以及筛选和高级排序功能。 此实现提供基于字符串值的筛选,并使用属性描述符和方向对进行多列排序。
-
实现 IEditableObject 接口的类允许对象控制何时将对该对象的更改永久化。 此实现支持BeginEdit和EndEditCancelEdit方法,使你能够回滚对对象所做的更改。 下面是对
BeginEdit
、EndEdit
和CancelEdit
方法功能的简要说明,以及它们如何相互配合以实现对已作数据更改的可能回滚:该方法 BeginEdit 指示对对象进行编辑的开始。 实现此接口的对象需要在调用
BeginEdit
方法后存储任何更新,以便若调用 CancelEdit 方法时可以放弃这些更新。 在数据绑定 Windows 窗体中,可以在单个编辑事务的范围内多次调用BeginEdit
(例如,BeginEdit
,,BeginEdit
EndEdit)。 实现IEditableObject时,应跟踪BeginEdit
是否已被调用,并忽略后续对BeginEdit
的调用。 由于此方法可以多次调用,因此重要的是后续调用不会改变或破坏现有内容。 后续BeginEdit
调用无法销毁已进行的更新或更改在第一次BeginEdit
调用中保存的数据。该方法 CancelEdit 放弃对对象所做的任何更改。
有关BeginEdit、EndEdit和CancelEdit方法的工作原理的更多信息,请参阅将数据保存回数据库。
此数据功能的事务概念由 DataGridView 控件使用。
-
通常情况下,类如果实现ICancelAddNew接口,通常也会实现IBindingList接口,并允许您使用AddNew方法回滚对数据源所做的添加。 如果数据源实现
IBindingList
接口,还应让它实现ICancelAddNew
接口。 -
实现接口的 IDataErrorInfo 类允许对象向绑定控件提供自定义错误信息:
IEnumerable 接口
实现接口的 IEnumerable 类通常由 ASP.NET 使用。 Windows 窗体对该接口的支持只能通过 BindingSource 组件获得。
注释
组件 BindingSource 将所有 IEnumerable 项复制到单独的列表中,以便进行绑定。
ITypedList 接口
实现 ITypedList 接口的集合类具有功能,以控制绑定控件中公开的属性的顺序和集合。
注释
实现 GetItemProperties 该方法且 PropertyDescriptor 数组不为 null 时,数组中的最后一个条目将是描述列表属性的属性描述符,该属性是另一个项列表。
-
实现接口的 ICustomTypeDescriptor 类提供有关自身的动态信息。 此接口类似于 ITypedList ,但用于对象而不是列表。 此接口用于 DataRowView 投影基础行的架构。 由CustomTypeDescriptor类提供了
ICustomTypeDescriptor
的简单实现。注释
若要支持对实现 ICustomTypeDescriptor的类型进行设计时绑定,该类型还必须实现 IComponent 并作为窗体上的实例存在。
IListSource 接口
实现接口的 IListSource 类对非列表对象启用基于列表的绑定。
IListSource
的 GetList 方法用于从不继承自 IList 的对象中返回可绑定列表。IListSource
由 DataSet 类使用。-
实现 IRaiseItemChangedEvents 接口的类是一个实现 IBindingList 接口的可绑定列表。 此接口用于指示您的类型是否通过其RaisesItemChangedEvents属性引发ItemChanged类型的ListChanged事件。
注释
如果数据源提供列出之前描述的事件转换的属性,并且与 BindingSource 组件交互,则应实现IRaiseItemChangedEvents。 否则,
BindingSource
它还将执行属性来列出事件转换,从而导致性能降低。 -
实现 ISupportInitialize 接口的组件利用批处理优化来设置属性和初始化依赖属性。
ISupportInitialize
包含两种方法: ISupportInitializeNotification 接口
实现ISupportInitializeNotification接口的组件也实现ISupportInitialize接口。 此接口允许你通知其他
ISupportInitialize
组件初始化已完成。 该ISupportInitializeNotification
接口包含两个成员:IsInitialized 返回一个
boolean
值,该值指示是否初始化组件。EndInit 在调用 Initialized 时发生。
-
实现此接口的类是在其任何属性值发生更改时引发事件的类型。 此接口旨在取代控件每个属性都有一个事件变化的模式。 在一个BindingList<T>环境中使用时,业务对象应实现INotifyPropertyChanged接口,BindingList'1 会将事件转换为PropertyChangedListChanged类型的ItemChanged事件。
注释
若要在绑定客户端和数据源之间的绑定中发生更改通知,绑定数据源类型应实现 INotifyPropertyChanged 接口(首选),也可以为绑定类型提供 propertyName
Changed
事件,但不应同时执行这两项作。
组件作者实现的接口
以下接口旨在供 Windows 窗体数据绑定引擎使用:
-
实现此接口的类是支持数据绑定的非控制组件。 通过此接口的 DataBindings 和 BindingContext 属性, 该类返回组件的数据绑定和绑定上下文。
注释
如果组件继承自 Control,则无需实现 IBindableComponent 接口。
-
实现 ICurrencyManagerProvider 接口的类是一个组件,它提供专属的 CurrencyManager 来管理与该特定组件相关联的绑定。 对自定义
CurrencyManager
的访问由 CurrencyManager 属性提供。注释
继承自 Control 的类会通过其 BindingContext 属性自动地管理绑定,因此,需要实现 ICurrencyManagerProvider 的情况相当罕见。
Windows Forms 支持的数据源
传统上,数据绑定已在应用程序中使用,以利用存储在数据库中的数据。 使用 Windows 窗体数据绑定,只要满足某些最低要求,就可以访问数据库和其他结构(如数组和集合)中的数据。
需绑定的结构体
在 Windows 窗体中,你可以绑定到各种结构,从简单对象(简单绑定)到复杂列表,例如 ADO.NET 数据表(复杂绑定)。 对于简单绑定,Windows 窗体支持将公共属性绑定到简单对象。 基于 Windows 窗体列表的绑定通常要求对象支持 IList 接口或 IListSource 接口。 此外,如果要通过 BindingSource 组件进行绑定,则可以绑定到支持 IEnumerable 接口的对象。
以下列表显示了可以在 Windows 窗体中绑定到的结构。
-
BindingSource 是最常见的 Windows 窗体数据源,在数据源和 Windows 窗体控件之间执行代理。 一般
BindingSource
使用模式是将控件绑定到BindingSource
并将BindingSource
绑定到数据源(例如 ADO.NET 数据表或业务对象)。BindingSource
提供了增强和改进数据绑定支持水平的服务。 例如,一些基于 Windows 窗体列表的控件(如 DataGridView 和 ComboBox)并不直接支持绑定到 IEnumerable 数据源,但是可以通过BindingSource
进行绑定来启用此方案。 在这种情况下,BindingSource
会将数据源转换为 IList。 简单对象
Windows 窗体支持通过 Binding 类型将数据绑定控件的属性绑定到对象实例的公共属性上。 Windows 窗体还支持基于绑定列表的控件,例如在使用 BindingSource 时将 ListControl 绑定到对象实例。
数组或集合
若要充当数据源,列表必须实现 IList 接口;一个示例是 Array 类的实例的数组。 有关数组的详细信息,请参阅 如何:创建对象数组(Visual Basic)。
通常,在为数据绑定创建对象列表时,应使用 BindingList<T>。
BindingList
是 IBindingList 接口的通用版本。IBindingList
接口通过添加双向数据绑定所需的属性、方法和事件来扩展 IList 接口。-
Windows 窗体控件可以绑定到仅支持 IEnumerable 接口的数据源,前提是它们通过 BindingSource 组件进行绑定。
ADO.NET 数据对象
ADO.NET 提供了许多适合绑定到的数据结构。 每一种都因其精密性和复杂性而异。
-
A DataColumn 是 DataTable 的基本构件,多个列构成一个表。 每个
DataColumn
都有一个 DataType 属性,用于确定该列包含的数据类型(例如,描述汽车的表中的汽车品牌)。 可以将控件(如 TextBox 控件的 Text 属性)简单绑定到数据表中的列。 -
DataTable 是表(行和列)在 ADO.NET 中的表示形式。 数据表包含两个集合:DataColumn,表示给定表中数据的列(最终确定可输入到该表中的数据种类),以及表示给定表中数据的行 DataRow。 可以将控件复杂绑定到数据表中包含的信息(例如将 DataGridView 控件绑定到数据表)。 但是,当你绑定到
DataTable
时,你会自动绑定到表的默认视图。 -
DataView 是一个可以筛选或排序的单一数据表的自定义视图。 数据视图是复杂绑定控件使用的数据“快照”。 可以简单绑定或复杂绑定到数据视图中的数据,但请注意,要绑定到数据的固定“图片”,而不是干净的更新数据源。
-
DataSet 是数据库中数据的表、关系和约束的集合。 可以简单绑定或复杂绑定到数据集中的数据,但请注意,要绑定到默认值 DataViewManager
DataSet
(请参阅下一个项目符号点)。 -
DataViewManager 是整个 DataSet的自定义视图,类似于 DataView,但包含关系。 使用 DataViewSettings 集合,可以为给定表
DataViewManager
具有的任何视图设置默认筛选器和排序选项。
-
数据绑定的类型
Windows 窗体可以利用两种类型的数据绑定:简单绑定和复杂绑定。 每个都提供不同的优势。
数据绑定的类型 | DESCRIPTION |
---|---|
简单数据绑定 | 控件绑定到单个数据元素的功能,例如数据集表中列中的值。 简单数据绑定是控件(如 TextBox 控件或 Label 控件)的典型绑定类型,这些控件通常只显示单个值。 事实上,控件上的任何属性都可以绑定到数据库中的字段。 Visual Studio 中对此功能有广泛的支持。 有关详细信息,请参阅“导航数据”和“创建简单绑定控件”(Windows 窗体 .NET)。 |
复杂数据绑定 | 控件绑定到多个数据元素(通常数据库中有多个记录)的能力。 复杂绑定也称为基于列表的绑定。 支持复杂绑定的控件的示例包括 DataGridView控件 ListBox和 ComboBox 控件。 有关复杂数据绑定的示例,请参阅 “如何:将 Windows 窗体 ComboBox 或 ListBox 控件绑定到数据”。 |
绑定源组件
为了简化数据绑定,Windows 窗体使你可以将数据源 BindingSource 绑定到组件,然后将控件绑定到该组件 BindingSource
。 可以在简单或复杂的绑定方案中使用 BindingSource
。 在任何情况下,该 BindingSource
都在数据源与绑定控件之间充当中介,提供变更通知、货币管理和其他服务。
使用数据绑定的常见方案
几乎每个商业应用程序都使用从一种或另一种类型的数据源读取的信息,通常通过数据绑定。 以下列表显示了一些最常见的情境,这些情境利用数据绑定作为数据呈现和操作的方法。
情景 | DESCRIPTION |
---|---|
报告 | 报表提供了一种灵活的方法来显示和汇总打印文档中的数据。 通常创建一个报表,该报表将数据源的选定内容打印到屏幕或打印机。 常见报表包括列表、发票和摘要。 项目被格式化为列表列,子项组织在每个列表项下,但你应该选择最适合数据的布局。 |
数据输入 | 输入大量相关数据或提示用户输入信息的常见方法是通过数据输入表单。 用户可以使用文本框、选项按钮、下拉列表和复选框输入信息或选择选项。 然后,将信息提交并存储在数据库中,其结构基于输入的信息。 |
主从关系 | 主/细节应用程序是用于查看相关数据的一种格式。 具体而言,在经典业务示例中,有两个数据表具有连接关系,即“Customers”表和一个“订单”表,它们与客户与其各自的订单之间存在关系。 有关使用两个 Windows 窗体 DataGridView 控件创建主/详细信息应用程序的详细信息,请参阅 如何:使用两个 Windows 窗体 DataGridView 控件创建主窗体/详细信息窗体。 |
查找表 | 另一个常见的数据呈现/作方案是表查找。 通常,作为较大数据显示的一部分, ComboBox 控件用于显示和作数据。 键是控件中显示的 ComboBox 数据与写入数据库的数据不同。 例如,如果你有一个 ComboBox 控件显示杂货店提供的物品,你可能希望看到产品的名称(面包,牛奶,鸡蛋)。 但是,为了简化数据库中的信息检索和数据库规范化,你可能会将给定订单的特定项的信息存储为项编号(#501、#603 等)。 因此,您的窗体中的ComboBox 控件内的杂货项目“友好名称”与订单中存在的相关项目编号存在隐式连接。 这是表格查找的本质。 有关详细信息,请参阅如何使用Windows Forms BindingSource组件创建查找表。 |