这个示例展示了如何在 Visual Studio 2005 的设计时刻,把一个 data-aware 控件 (XtraGrid、XtraPivotGrid、XtraVerticalGrid 等) 绑定到数据库。 注意,在控件被绑定到数据源之后,特定的控件可能需要额外进行定制。 关于这一问题的信息,请参阅相应控件的文档。
在本例中,一个 GridControl 控件被绑定到数据源,来呈现主/从关系。
Microsoft Visual Studio 2005 引入了 System.Windows.Forms.BindingSource 组件,可简化 data-aware 控件到数据的绑定。 请参阅 MSDN 中的 BindingSource 组件 [Windows 窗体] 主题。
本主题展示如何使用 BindingSource 组件把 XtraGrid 控件绑定到 NorthWind 数据库中的 "Orders" 和 "Order Details" 表 (nwind.mdb 文件与 data-aware DevExpress 控件的安装一同提供)。 这些表通过“一对多”关系链接 (第一个表中的一行,可以与第二个表中的一行或多行相关联;但是第二个表中的一行,只与第一个表中的一行相关联)。 在这个示例中,网格控件将把这些表呈现为主表和从表级(视图)。
在你执行完本示例中的下列步骤之后, 结果将与下面类似:
步骤 1-8. 创建数据对象
- 在 Visual Studio 2005 中新建一个项目。
- 在“工具箱”的“数据”组中找到 BindingSource 组件,并把它拖放到一个窗体上。 一个新的组件 (bindingSource1) 将会出现在窗体设计器底部的面板中。
-
在底部面板中选中 bindingSource1 组件,并打开“属性”窗口 (例如,通过按下 F4 键)。 然后为 DataSource 属性打开下拉表,并在它的底部单击“添加项目数据源(Add Project Data Source)...”链接。
一个允许你选择需绑定数据源的对话框将出现。
-
选择数据库图标。单击[下一步]。
-
在下一个页面中指定 NorthWind 数据库的路径,然后单击[下一步]。 在下面的、询问是否将所创建的连接字符串保存到配置文件的页面中,也单击[下一步]。
-
下一个页面允许你选择需要从数据库中获取哪些表。 选中 "Orders" 和 "Order Details" 表,并单击[完成]。
结果,Visual Studio 将生成一组支持 ADO.NET 架构的类。 一些主要的类是:
- OrdersDataTable —— 呈现一个 DataTable 对象,将包含来自 NorthWind 数据库 "Orders" 表中的记录;
- Order_DetailsDataTable —— 呈现一个 DataTable 对象,将包含来自 NorthWind 数据库 "Orders Details" 表中的记录;
- nwindDataSet —— 呈现一个 DataSet 对象 (可相互关联的表的一个集合)。 这个生成的 DataSet 包含中了 OrdersDataTable 和 Order_DetailsDataTable 表,并指定了这两个表之间的一对多关系。
- OrdersTableAdapter —— 呈现一个 TableAdapter 对象,可与 NorthWind 数据库中的 "Orders" 表通信。 TableAdapter 对象包含了从数据库表中获取数据的方法,和将数据传送到数据库表中的方法。
- Order_DetailsTableAdapter —— 呈现一个 TableAdapter 对象,可与 NorthWind 数据库中的 "Orders Details" 表通信。
当以上面所示的方法连接数据库时, Visual Studio 自动把 nwindDataSet 类的一个实例添加到窗体设计器的底部面板中。 你可以检查生成的数据集中是否包含了 OrdersDataTable 和 Order_DetailsDataTable 表。 要执行此操作,可在底部面板中选中 nwindDataSet 组件,并单击“在数据集设计器中编辑(Edit Data in DataSet Designer)...”任务:
数据规划将被打开,如下图所示:
你可以看到,两个表被自动通过关系进行链接。 关系信息已经从数据库中取出。
-
切换到窗体设计器,并重新生成项目。 在项目被成功生成之后,工具箱中将包含那些呈现已生成类的新项:nwindDataSet、 OrdersTableAdapter 和 Order_DetailsTableAdapter。
-
在工具箱中选中 OrdersTableAdapter 组件,并把它拖放到窗体上。 对 Order_DetailsTableAdapter 组件重复这种操作。 这些组件的新实例将出现在窗体设计器的底部面板中。
步骤 9-10. 绑定到 Grid
- 把 XtraGrid 组件拖放到窗体中。
-
这个网格控件必须被绑定到主表 ("Orders")。 在数据集中主/从关系所标识的从表数据将被自动获取并呈现为细节视图。 要绑定这个网格控件,可把它的 DataSource 属性设置为 "bindingSource1",把 DataMember 属性设置为 "Orders":
在网格控件被绑定后,它自动为下层表中的所有字段创建网格列。 也请注意,在设计时刻这个网格控件显示了主/从展开按钮,指明下层数据源中包含了从表数据。
现在如果运行项目,那么网格控件将是空的,因为下层的 OrdersDataTable 没有包含数据。 要使用数据装载它,需要编写如下面的步骤所示的代码。
步骤 11. 在运行时刻载入数据
-
要从数据库中为 DataTable 对象载入数据,则可以使用相应的 TableAdapter.Fill 方法。 在本例中, 使用 OrdersTableAdapter 和 Order_DetailsTableAdapter 对象(已经从工具箱中把它们拖放到窗体设计器的底层面板中)的 Fill 方法,为 OrdersDataTable 和 Order_DetailsDataTable 表载入数据。 窗体的 Load 事件被使用,来管理数据的加载:
1 private void Form1_Load(object sender, EventArgs e) { 2 ordersTableAdapter1.Fill(nwindDataSet.Orders); 3 order_DetailsTableAdapter1.Fill(nwindDataSet.Order_Details); 4 }
现在如果运行这个项目,将会得到与下图相似的结果:
步骤 12-14. 定制网格
-
隐藏列
这个网格的主视图(gridView1) 包含了过多的列。 尽管可以使用一个高级的有带区的网格视图(an Advanced Banded Grid View) 来在多个行中安排这些列,但我们只隐藏一些特定的列。 例如,隐藏 "ShippedDate" 列 —— 把它的标头拖出标头面板并放下 (鼠标指针将把它的形状改变为有十字叉)。
-
创建细节视图
你可能注意到了在设计时刻,呈现从表("Order Details") 的细节视图还没有创建。 只有主表视图(gridView1) 被创建。 如果在设计时刻没有创建细节视图,那么在运行时刻,当主控行被展开时, XtraGrid 控件自动创建细节视图(基于主表视图的设置)。 要在设计时刻能够定制细节视图,你需要创建一个模式细节视图,例如使用网格控件的层级设计器(Level Designer)。
在层级设计器中单击 Retrieve Details(取回细节) 按钮。 在接下来显示的对话框中单击[是]按钮。 结果, XtraGrid 返回所有下层数据源中的主/从关系,并把它们作为层呈现。 在本例中,只有一个细节层被创建。 它的名称 ("OrdersOrder Details") 与关系名相匹配:
现在可以把一个特定的视图指派到所创建的细节层中。 单击 "Click here to change view(单击此处修改视图)" 链接,并选择“Create new view(新建视图) -> GridView”命令。
这个网格将创建一个 GridView 类型的新视图,并把它与 "OrdersOrder Details" 层关联。 层级设计器的外观将与下图相像:
在层级设计器(选中这个视图)中单击 gridView2 链接,然后在“属性”窗口中单击 Columns 链接:
这会打开网格控件设计器的 Columns(列) 页面。 单击 Retrieve Fields(取回字段) 按钮,为下层从表中的所有字段创建列。
在关闭设计器时, gridView2 将显示所有源自 "Order Details" 表的列。
-
其他任务
你可能需要使用这个网格控件来执行许多任务。 为了帮助你找出与特定功能相关联的选项,可使用 功能浏览器(Feature Browser),它可以通过网格控件的设计器进行访问。 这是一个能找出许多问题的答案的、功能强大的工具。
步骤 15. 把数据传回数据库
-
你可以运行这个项目,并开始编辑数据。 所作出的修改将被保存在下层 DataTable 对象中,但不会保存在数据库中。 要完成这个示例,需要编写代码把在 OrdersDataTable 和 Order_DetailsDataTable 表中的改变传回数据库中。 接管 FormClosing 事件来实现此目标:
1 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { 2 DevExpress.XtraGrid.Views.Base.BaseView view = gridControl1.FocusedView; 3 if (!(view.PostEditor() && view.UpdateCurrentRow())) { 4 e.Cancel = true; 5 return; 6 } 7 ordersTableAdapter1.Update(nwindDataSet.Orders); 8 order_DetailsTableAdapter1.Update(nwindDataSet.Order_Details); 9 }
结果
下面的插图展示了在运行时刻形成的网格控件:
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------分割线----
以上是复制的原文档,下面是我实现的主从表数据绑定。
数据库:
控件:
我添加的代码:
1 //在运行时刻载入数据 2 private void Form1_Load(object sender, EventArgs e) 3 { 4 productsTableAdapter1.Fill(nwindDataSet.Products); 5 categoriesTableAdapter1.Fill(nwindDataSet.Categories); 6 } 7 //把数据传回数据库 8 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 9 { 10 DevExpress.XtraGrid.Views.Base.BaseView view = gridControl1.FocusedView; 11 if (!(view.PostEditor() && view.UpdateCurrentRow())) 12 { 13 e.Cancel = true; 14 return; 15 } 16 productsTableAdapter1.Update(nwindDataSet.Products); 17 categoriesTableAdapter1.Update(nwindDataSet.Categories); 18 }
结果: