带详细编辑窗体的 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 中的索引来确定的。


