演练:使用两个 Windows 窗体 DataGridView 控件创建一个主/从窗体
使用 DataGridView 控件的最常见方案之一是主/详细信息窗体,其中显示了两个数据库表之间的父/子关系。 选择主表中的行后,详细信息表会使用相应的子数据进行更新。
通过 DataGridView 控件和 BindingSource 组件之间的交互可以轻松实现主/详细信息窗体。 在本演练中,你将使用两个 DataGridView 控件和两个 BindingSource 组件生成窗体。 窗体将显示 Northwind SQL Server 示例数据库中的两个相关表:Customers
和 Orders
。 完成后,将会有一个窗体,其中显示了主 DataGridView 的数据库中的所有客户,以及详细信息 DataGridView 中所选客户的所有订单。
若要将本主题中的代码复制为单个列表,请参阅如何:使用两个 Windows 窗体 DataGridView 控件创建主/详细信息窗体。
先决条件
若要完成本演练,你将需要:
- 可访问具有 Northwind SQL Server 示例数据库的服务器。
创建窗体
创建主/详细信息窗体
创建派生自 Form 并包含两个 DataGridView 控件和两个 BindingSource 组件的类。 以下代码提供基本窗体初始化并包含一个
Main
方法。 如果使用 Visual Studio 设计器创建窗体,则可以使用设计器生成的代码而不是此代码,但请务必使用此处变量声明中显示的名称。using System; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; public class Form1 : System.Windows.Forms.Form { private DataGridView masterDataGridView = new DataGridView(); private BindingSource masterBindingSource = new BindingSource(); private DataGridView detailsDataGridView = new DataGridView(); private BindingSource detailsBindingSource = new BindingSource(); [STAThreadAttribute()] public static void Main() { Application.Run(new Form1()); } // Initializes the form. public Form1() { masterDataGridView.Dock = DockStyle.Fill; detailsDataGridView.Dock = DockStyle.Fill; SplitContainer splitContainer1 = new SplitContainer(); splitContainer1.Dock = DockStyle.Fill; splitContainer1.Orientation = Orientation.Horizontal; splitContainer1.Panel1.Controls.Add(masterDataGridView); splitContainer1.Panel2.Controls.Add(detailsDataGridView); this.Controls.Add(splitContainer1); this.Load += new System.EventHandler(Form1_Load); this.Text = "DataGridView master/detail demo"; }
Imports System.Data Imports System.Data.SqlClient Imports System.Windows.Forms Public Class Form1 Inherits System.Windows.Forms.Form Private masterDataGridView As New DataGridView() Private masterBindingSource As New BindingSource() Private detailsDataGridView As New DataGridView() Private detailsBindingSource As New BindingSource() <STAThreadAttribute()> _ Public Shared Sub Main() Application.Run(New Form1()) End Sub ' Initializes the form. Public Sub New() masterDataGridView.Dock = DockStyle.Fill detailsDataGridView.Dock = DockStyle.Fill Dim splitContainer1 As New SplitContainer() splitContainer1.Dock = DockStyle.Fill splitContainer1.Orientation = Orientation.Horizontal splitContainer1.Panel1.Controls.Add(masterDataGridView) splitContainer1.Panel2.Controls.Add(detailsDataGridView) Me.Controls.Add(splitContainer1) Me.Text = "DataGridView master/detail demo" End Sub
}
End Class
在窗体的类定义中实现一个方法,用于处理连接到数据库的详细信息。 此示例使用填充 DataSet 对象、将 DataRelation 对象添加到数据集并绑定 BindingSource 组件的
GetData
方法。 请确保将connectionString
变量设置为适合数据库的值。重要
将敏感信息(如密码)存储在连接字符串中可能会影响应用程序的安全性。 若要控制对数据库的访问,一种较为安全的方法是使用 Windows 身份验证(也称为集成安全性)。 有关详细信息,请参阅保护连接信息。
private void GetData() { try { // Specify a connection string. Replace the given value with a // valid connection string for a Northwind SQL Server sample // database accessible to your system. String connectionString = "Integrated Security=SSPI;Persist Security Info=False;" + "Initial Catalog=Northwind;Data Source=localhost"; SqlConnection connection = new SqlConnection(connectionString); // Create a DataSet. DataSet data = new DataSet(); data.Locale = System.Globalization.CultureInfo.InvariantCulture; // Add data from the Customers table to the DataSet. SqlDataAdapter masterDataAdapter = new SqlDataAdapter("select * from Customers", connection); masterDataAdapter.Fill(data, "Customers"); // Add data from the Orders table to the DataSet. SqlDataAdapter detailsDataAdapter = new SqlDataAdapter("select * from Orders", connection); detailsDataAdapter.Fill(data, "Orders"); // Establish a relationship between the two tables. DataRelation relation = new DataRelation("CustomersOrders", data.Tables["Customers"].Columns["CustomerID"], data.Tables["Orders"].Columns["CustomerID"]); data.Relations.Add(relation); // Bind the master data connector to the Customers table. masterBindingSource.DataSource = data; masterBindingSource.DataMember = "Customers"; // Bind the details data connector to the master data connector, // using the DataRelation name to filter the information in the // details table based on the current row in the master table. detailsBindingSource.DataSource = masterBindingSource; detailsBindingSource.DataMember = "CustomersOrders"; } catch (SqlException) { MessageBox.Show("To run this example, replace the value of the " + "connectionString variable with a connection string that is " + "valid for your system."); } }
Private Sub GetData() Try ' Specify a connection string. Replace the given value with a ' valid connection string for a Northwind SQL Server sample ' database accessible to your system. Dim connectionString As String = _ "Integrated Security=SSPI;Persist Security Info=False;" & _ "Initial Catalog=Northwind;Data Source=localhost" Dim connection As New SqlConnection(connectionString) ' Create a DataSet. Dim data As New DataSet() data.Locale = System.Globalization.CultureInfo.InvariantCulture ' Add data from the Customers table to the DataSet. Dim masterDataAdapter As _ New SqlDataAdapter("select * from Customers", connection) masterDataAdapter.Fill(data, "Customers") ' Add data from the Orders table to the DataSet. Dim detailsDataAdapter As _ New SqlDataAdapter("select * from Orders", connection) detailsDataAdapter.Fill(data, "Orders") ' Establish a relationship between the two tables. Dim relation As New DataRelation("CustomersOrders", _ data.Tables("Customers").Columns("CustomerID"), _ data.Tables("Orders").Columns("CustomerID")) data.Relations.Add(relation) ' Bind the master data connector to the Customers table. masterBindingSource.DataSource = data masterBindingSource.DataMember = "Customers" ' Bind the details data connector to the master data connector, ' using the DataRelation name to filter the information in the ' details table based on the current row in the master table. detailsBindingSource.DataSource = masterBindingSource detailsBindingSource.DataMember = "CustomersOrders" Catch ex As SqlException MessageBox.Show("To run this example, replace the value of the " & _ "connectionString variable with a connection string that is " & _ "valid for your system.") End Try End Sub
为窗体的 Load 事件实现处理程序,将 DataGridView 控件绑定到 BindingSource 组件并调用
GetData
方法。 以下示例包含用于调整 DataGridView 列大小以适应显示数据的代码。private void Form1_Load(object sender, System.EventArgs e) { // Bind the DataGridView controls to the BindingSource // components and load the data from the database. masterDataGridView.DataSource = masterBindingSource; detailsDataGridView.DataSource = detailsBindingSource; GetData(); // Resize the master DataGridView columns to fit the newly loaded data. masterDataGridView.AutoResizeColumns(); // Configure the details DataGridView so that its columns automatically // adjust their widths when the data changes. detailsDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; }
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Load ' Bind the DataGridView controls to the BindingSource ' components and load the data from the database. masterDataGridView.DataSource = masterBindingSource detailsDataGridView.DataSource = detailsBindingSource GetData() ' Resize the master DataGridView columns to fit the newly loaded data. masterDataGridView.AutoResizeColumns() ' Configure the details DataGridView so that its columns automatically ' adjust their widths when the data changes. detailsDataGridView.AutoSizeColumnsMode = _ DataGridViewAutoSizeColumnsMode.AllCells End Sub
测试应用程序
现在可以测试窗体,以确保它的行为符合预期。
测试窗体
编译并运行该应用程序。
你将看到两个 DataGridView 控件,一个在另一个之上。 顶部是 Northwind
Customers
表中的客户,底部是与所选客户对应的Orders
。 在顶部的 DataGridView 中选择不同的行后,底部 DataGridView 的内容会随之更改。
后续步骤
此应用程序让你对 DataGridView 控件的功能有了一个基本的了解。 可以通过多种方式自定义 DataGridView 控件的外观和行为:
更改边框和标题样式。 有关详细信息,请参阅如何:更改 Windows 窗体 DataGridView 控件中的边框和网格线样式。
启用或限制对 DataGridView 控件的用户输入。 有关详细信息,请参阅如何:防止在 Windows 窗体 DataGridView 控件中添加和删除行和如何:将 Windows 窗体 DataGridView 控件中的列设为只读。
验证对 DataGridView 控件的用户输入。 有关详细信息,请参阅演练:验证 Windows 窗体 DataGridView 控件中的数据。
使用虚拟模式处理海量数据集。 有关详细信息,请参阅演练:在 Windows 窗体 DataGridView 控件中实现虚拟模式。
自定义单元格的外观。 有关详细信息,请参阅如何:自定义 Windows 窗体 DataGridView 控件中单元格的外观和如何:设置 Windows 窗体 DataGridView 控件的默认单元格样式。
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈