使用 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在窗体的类定义中实现一个方法,用于处理连接到数据库的详细信息。 此示例使用填充
GetData对象的 DataSet 方法,将 DataRelation 对象添加到数据集,并绑定 BindingSource 组件。 请务必将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 控件的默认单元格样式。