带详细编辑窗体的 DataGridView - VS 2005






4.36/5 (27投票s)
如何使用强类型数据集数据层创建一个带关联的详细编辑窗体的DataGridView。
引言
本文是一篇教程,介绍如何使用强类型的 DataSet
数据层,创建一个可选择的 WinForms datagridview
,并带有一个独立的窗体用于编辑详细行数据。我们将使用 Visual Studio 2005 和 .NET 2.0。
背景
创建一个可编辑的 datagrid
是编辑 datagrid
值的非常直接的方法,但有时需要一个独立的、可编辑的 Form
/UserControl
(增加灵活性,更多细节等)。本示例将在窗体加载时加载可编辑字段和查找项。这将使我们不必同步和管理类似数据的独立实例,并减少往返数据库的次数。当处理大量记录时,您可能希望在查询中实现 where
过滤器。我们将在编辑窗体中包含一个 Save
按钮。Save
按钮可以很容易地实现在主窗体上。也可以将编辑窗体更改为 UserControl
,以便在主窗体上显示而不是弹出。
演练
1. 添加数据源(强类型数据集)
- 创建一个新的 Windows Forms 项目,并创建两个窗体:
Orders
和Order
。 - 在设计视图中打开
Orders
。 - 在“数据源”窗口中点击“
添加新数据源
”。 - 选择“
数据库
”作为数据源类型。 - 创建新连接。
- 选择“
Microsoft SQL Server (SqlClient)
”作为数据源。 - 输入 Northwind 数据库的位置和登录凭据。
- 一直点击“下一步”,直到出现“选择数据库对象”。
- 从
Orders
表中选择OrderID
、CustomerID
和EmployeeID
,从Customers
表中选择CustomerID
、CompanyName
和ContactName
,以及从Employees
表中选择EmployeeID
、LastName
、FirstName
和Title
,如下所示: - 点击**完成**。
注意
这会自动创建
NorthwindDataSet
强类型数据集,并包含相关的表/TableAdapters。 - 在“数据源”窗口中将
CustomerID
和EmployeeID
列更改为ComboBoxes
。
2. 创建 DataGridView
- 将
Orders
表从“数据源”窗口拖到Orders
窗体上。 - 这将创建一个
NorthWindDataSet
实例、一个BindingSource
和一个BindingNavigator
。 - 删除
BindingNavigator
。 - 点击
DataGridView
的“智能标签”以打开“DataGridView
任务”窗口。 - 禁用编辑、删除和添加。然后将其停靠在父容器中。
- 点击“
编辑列...
”。将CustomerID
和EmployeeID
列更改为DataGridViewComboBoxColumn
列类型。 - 为
Customer
和Employee
列绑定Datasource
、DisplayMember
和ValueMember
属性。注意
从“
项目数据源
”节点选择数据源会自动为窗体创建BindingSources
和TableAdapters
。 - 将这两列的
DisplayStyle
设置为Nothing
,因为它们将是只读的。
3. 创建编辑窗体
- 在设计视图中打开
Order
窗体。 - 将“数据源”窗口中的
NorthwindDataSet.Orders
表从“DataGridView
”更改为“Details
”。 - 将详细表从“数据源”窗口拖到
Order
窗体上。这将在窗体上创建 3 个控件,以及DataSet
、BindingSource
、TableAdapter
和BindingNavigator
。 - 删除
BindingNavigator
。 - 将一个
Button
控件拖到窗体上,并将其重命名为ButtonSave
。 - 点击每个
ComboBoxes
的“智能标签”,编辑DataSource
、DisplayMember
、SelectedValue
和ValueMember
属性,就像之前对GridViewComboBoxColumns
所做的那样。
您必须勾选“使用数据绑定项
”选项才能编辑这些值。 - 这将为
Employees
和Customers
表在窗体上创建BindingSource
和TableAdapter
组件。 - 删除相应的
TableAdapters
(但保留OrdersTableAdapter
),因为我们将从Orders
窗体填充这些表。 - 将
DataBindings.Text
属性设置为None
,因为我们现在绑定到SelectedValue
属性。
4. 实例化编辑窗体
- 在编辑窗体中创建一个
Sub New()
。 - 在设计模式下双击“
Save
”按钮以创建点击事件处理程序。 - 使用以下代码(修复任何命名差异)
Private Sub Orders_FormClosing(ByVal sender As Object, _ ByVal e As System.Windows.Forms.FormClosingEventArgs) _ Handles Me.FormClosing 'Reject any changes that were not saved. Me.NorthwindDataSet.Orders(Me.OrdersBindingSource.Position)._ RejectChanges() End Sub Private Sub ButtonSave_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ButtonSave.Click 'Update the database and close. Me.Validate() Me.OrdersBindingSource.EndEdit() If Not Me.OrdersTableAdapter.Update(Me.NorthwindDataset.Orders) > 0 _ Then MsgBox("No records were updated.") End If Me.Close() End Sub Public Sub New(ByVal nwDataSet As NorthwindDataSet, _ ByVal position As Integer) ' This call is required by the Windows Form Designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. ' We will specify the DataSet from the DataGrid form here Me.NorthwindDataset = nwDataSet Me.OrdersBindingSource.DataSource = Me.NorthwindDataSet Me.CustomersBindingSource.DataSource = Me.NorthwindDataSet Me.EmployeesBindingSource.DataSource = Me.NorthwindDataSet Me.OrdersBindingSource.Position = position End Sub Private Sub Order_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Do not refill. You could optionally refresh this record or 'access additional database columns by creating another query 'with a primary key parameter in the table adapter. 'Me.OrdersTableAdapter.Fill(Me.nwDataSet.Orders) End Sub
注意
在
Sub New
中,我们将传入由网格创建并填充的dataset
。然后我们将本地的NorthwindDataSet
变量指向现有的dataset
。这不会改变InitializeComponent
中为DataSet
设置的属性,因此我们必须重新配置窗体上的其他元素以指向现有的DataSet
。幸运的是,BindingSources
提供了抽象。我们只需要重置 3 个BindingSources
的DataSource
属性。然后我们设置BindingSource
的位置,以便窗体知道要编辑哪个记录。 - 在单击“保存”时,我们将保存更改并退出。
- 最后,在窗体关闭时,我们将撤销任何未保存的更改,因为
dataset
与网格共享。
5. 编码 DataGridView 双击事件
- 在代码视图中打开
Orders
窗体。 - 创建一个
RowHeaderMouseDoubleClick
事件处理程序。 - 创建一个
FormClosing
事件处理程序。 - 使用以下代码(修复任何命名差异)
Private Sub Orders_FormClosing(ByVal sender As Object, _ ByVal e As System.Windows.Forms.FormClosingEventArgs) _ Handles Me.FormClosing Me.OrdersDataGridView.Dispose() End Sub Private Sub Orders_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'TODO: This line of code loads data into the ''NorthwindDataSet.Employees' table. 'You can move, or remove it, as needed. Me.EmployeesTableAdapter.Fill(Me.NorthwindDataSet.Employees) 'TODO: This line of code loads data into the ''NorthwindDataSet.Customers' table. 'You can move, or remove it, as needed. Me.CustomersTableAdapter.Fill(Me.NorthwindDataSet.Customers) 'TODO: This line of code loads data into the ''NorthwindDataSet.Orders' table. 'You can move, or remove it, as needed. Me.OrdersTableAdapter.Fill(Me.NorthwindDataSet.Orders) End Sub Private Sub OrdersDataGridView_RowHeaderMouseDoubleClick_ (ByVal sender As Object, ByVal e _ As System.Windows.Forms.DataGridViewCellMouseEventArgs) _ Handles OrdersDataGridView.RowHeaderMouseDoubleClick If Me.OrdersDataGridView.SelectedRows.Count > 0 Then Dim editForm As New Order(Me.NorthwindDataSet, _ Me.NorthwindDataSet.Orders.Rows.IndexOf_ (CType(CType(Me.OrdersDataGridView.SelectedRows(0)._ DataBoundItem, DataRowView).Row, NorthwindDataSet.OrdersRow))) editForm.Show() End If End Sub
注意
DataSet
在窗体加载时填充。tableadapter
填充语句是通过配置 BindingSource
创建的。在窗体关闭之前,我们必须处理掉网格,以避免 GridViewComboBoxColumns
可能出现的 DataErrors
。
双击事件会实例化详细编辑窗体,传入 DataSet
和位置。位置是通过跟踪所选行到其在订单表中的行实例,然后找到该行在 dataset
中的索引来确定的。