DataGridView 用法教程:从入门到精通

DataGridView 是 Windows Forms 中功能最强大、最灵活的数据显示控件,它以表格形式展示数据,并支持丰富的交互功能,如排序、筛选、编辑和删除。

datagridview用法教程
(图片来源网络,侵删)

第一部分:基础入门

添加 DataGridView 控件

  1. 在 Visual Studio 中,打开或创建一个 Windows 窗体应用程序项目。
  2. 从“工具箱”中找到 DataGridView 控件。
  3. 将其拖放到你的窗体上。

通过设计器绑定数据(最简单的方式)

这是最直观的方式,适合快速展示静态数据或来自数据库的数据。

示例:绑定一个数据表

假设你有一个名为 Products 的数据表,包含 ID, ProductName, Price, Stock 等列。

  1. 在窗体上选中 DataGridView 控件。
  2. 在“属性”窗口中,找到 DataSource 属性。
  3. 点击下拉箭头,选择“添加项目数据源...”。
  4. 在弹出的向导中,选择“数据库”,然后点击“下一步”。
  5. 选择你的数据连接(或新建一个),选择数据库对象,Products 表,点击“完成”。
  6. DataGridView 会自动生成列并填充数据。

优点:快速、可视化,无需编写代码。 缺点:灵活性较低,不适合动态数据。

datagridview用法教程
(图片来源网络,侵删)

通过代码绑定数据(最常用、最灵活的方式)

在实际开发中,我们通常在代码中动态地为 DataGridView 提供数据,最常见的数据源是 DataTableBindingList。

示例 1:绑定 DataTable

using System;
using System.Data;
using System.Windows.Forms;
namespace DataGridViewTutorial
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            // 1. 创建一个 DataTable
            DataTable productsTable = new DataTable("Products");
            // 2. 定义列(列名和数据类型)
            productsTable.Columns.Add("ID", typeof(int));
            productsTable.Columns.Add("ProductName", typeof(string));
            productsTable.Columns.Add("Price", typeof(decimal));
            productsTable.Columns.Add("Stock", typeof(int));
            // 3. 添加数据行
            productsTable.Rows.Add(1, "笔记本电脑", 5999.99m, 50);
            productsTable.Rows.Add(2, "无线鼠标", 99.50m, 200);
            productsTable.Rows.Add(3, "机械键盘", 499.00m, 100);
            productsTable.Rows.Add(4, "USB-C 扩展坞", 299.99m, 150);
            // 4. 将 DataTable 绑定到 DataGridView
            dataGridView1.DataSource = productsTable;
        }
    }
}

示例 2:绑定 BindingList (推荐用于可编辑数据)

BindingList<T> 是一个实现了 IBindingList 接口的泛型列表,当列表中的数据发生变化时,DataGridView 会自动更新,非常适合用于数据绑定。

datagridview用法教程
(图片来源网络,侵删)

定义一个产品类:

public class Product
{
    public int ID { get; set; }
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
}

然后在窗体代码中绑定数据:

using System;
using System.ComponentModel; // 需要引入这个命名空间
using System.Windows.Forms;
namespace DataGridViewTutorial
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            // 1. 创建一个 BindingList<Product>
            BindingList<Product> productList = new BindingList<Product>();
            // 2. 添加产品对象
            productList.Add(new Product { ID = 1, ProductName = "笔记本电脑", Price = 5999.99m, Stock = 50 });
            productList.Add(new Product { ID = 2, ProductName = "无线鼠标", Price = 99.50m, Stock = 200 });
            productList.Add(new Product { ID = 3, ProductName = "机械键盘", Price = 499.00m, Stock = 100 });
            productList.Add(new Product { ID = 4, ProductName = "USB-C 扩展坞", Price = 299.99m, Stock = 150 });
            // 3. 将 BindingList 绑定到 DataGridView
            dataGridView1.DataSource = productList;
        }
    }
}

第二部分:常用属性与自定义

列的属性

DataGridView 上点击智能标签(右上角的小箭头),选择“编辑列...”或在属性窗口中找到 Columns 属性,可以打开“编辑列”对话框。

属性名 说明
Name 列的编程名称,用于在代码中引用该列。
HeaderText 列在表头中显示的文本。
Visible true/false,控制列是否可见。
ReadOnly true/false,控制该列的单元格是否可编辑。
ValueType 指定该列单元格的数据类型(如 typeof(int), typeof(string))。
AutoSizeMode 设置列的自动调整大小模式,常用值:
- None: 不自动调整。
- AllCells: 根据所有单元格内容调整。
- Fill: 列宽填充可用空间(常用)。
DefaultCellStyle 设置单元格的默认样式(字体、颜色、对齐方式等)。

代码示例:

// 通过代码添加和配置列
dataGridView1.AutoGenerateColumns = false; // 禁止自动生成列,以便我们手动控制
DataGridViewTextBoxColumn idColumn = new DataGridViewTextBoxColumn();
idColumn.Name = "ID";
idColumn.HeaderText = "产品ID";
idColumn.DataPropertyName = "ID"; // 绑定到数据源的哪个属性
idColumn.ReadOnly = true;
DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn();
nameColumn.Name = "ProductName";
nameColumn.HeaderText = "产品名称";
nameColumn.DataPropertyName = "ProductName";
DataGridViewTextBoxColumn priceColumn = new DataGridViewTextBoxColumn();
priceColumn.Name = "Price";
priceColumn.HeaderText = "价格";
priceColumn.DataPropertyName = "Price";
priceColumn.DefaultCellStyle.Format = "C2"; // 格式化为货币,保留两位小数
// 将列添加到 DataGridView
dataGridView1.Columns.AddRange(new DataGridViewColumn[] { idColumn, nameColumn, priceColumn });

行和单元格的属性

属性名 说明
AllowUserToAddRows true/false,是否允许用户通过底部的空白行添加新数据。
AllowUserToDeleteRows true/false,是否允许用户通过右键菜单或 Delete 键删除行。
MultiSelect true/false,是否允许选择多行或多列。
SelectionMode 选择模式,如 FullRowSelect(整行选中)、CellSelect(单个单元格选中)。
BackgroundColor 控件的背景色。
AlternatingRowsDefaultCellStyle 设置奇数行或偶数行的不同样式,以增强可读性。

第三部分:处理事件

事件是 DataGridView 交互的核心,以下是几个最重要的事件:

CellClick / CellDoubleClick

当用户点击或双击单元格时触发。

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // e.RowIndex 是被点击的行索引
    // e.ColumnIndex 是被点击的列索引
    // 检查是否点击了行头(无效点击)
    if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
    {
        // 获取被点击的单元格
        DataGridViewCell clickedCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        MessageBox.Show($"你点击了: 行 {e.RowIndex}, 列 {e.ColumnIndex}\n内容: {clickedCell.Value}");
    }
}

CellFormatting (单元格格式化)

在单元格显示内容之前触发,可以用来动态改变单元格的样式或显示值。

示例:将“Stock”列小于100的单元格背景色标红

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    // 我们只关心 "Stock" 这一列
    if (dataGridView1.Columns[e.ColumnIndex].Name == "Stock")
    {
        // 确保值是整数
        if (e.Value is int stock)
        {
            if (stock < 100)
            {
                // 将单元格的背景色设置为红色
                e.CellStyle.BackColor = Color.LightCoral;
            }
        }
    }
}

CellValueChanged (单元格值已更改)

当用户编辑单元格并按下 Enter 或离开单元格后,值发生变化时触发。

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0)
    {
        // 获取被修改的行
        DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
        MessageBox.Show($"第 {e.RowIndex + 1} 行的数据已更新!");
        // 在这里可以添加代码,将更新后的数据保存回数据库
    }
}

UserAddedRow / UserDeletedRow (用户添加/删除行)

当用户通过界面添加或删除行时触发。

private void dataGridView1_UserAddedRow(object sender, DataGridViewRowEventArgs e)
{
    MessageBox.Show("用户添加了一行新数据。");
    // 在这里可以生成新ID,或执行其他初始化操作
}
private void dataGridView1_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
{
    MessageBox.Show("用户删除了一行数据。");
    // 在这里可以从数据库中删除对应记录
}

第四部分:高级技巧

添加按钮列

允许在每一行添加一个按钮,用于执行特定操作(如编辑、删除)。

// 在设计器或代码中添加一个 DataGridViewButtonColumn
DataGridViewButtonColumn deleteButtonColumn = new DataGridViewButtonColumn();
deleteButtonColumn.Name = "DeleteButton";
deleteButtonColumn.HeaderText = "操作";
deleteButtonColumn.Text = "删除"; // 按钮上显示的文本
deleteButtonColumn.UseColumnTextForButtonValue = true; // 所有按钮都使用 Text 属性的值
dataGridView1.Columns.Add(deleteButtonColumn);

然后处理 CellClick 事件:

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // 检查是否点击了“删除”按钮列
    if (e.RowIndex >= 0 && dataGridView1.Columns[e.ColumnIndex] is DataGridViewButtonColumn)
    {
        // 获取要删除的行
        DataGridViewRow rowToDelete = dataGridView1.Rows[e.RowIndex];
        // 显示确认对话框
        DialogResult result = MessageBox.Show("确定要删除这条记录吗?", "确认删除", MessageBoxButtons.YesNo);
        if (result == DialogResult.Yes)
        {
            // 从数据源中移除
            if (dataGridView1.DataSource is BindingList<Product> productList)
            {
                // 找到并移除对应的对象
                Product productToDelete = productList[rowToDelete.Index];
                productList.Remove(productToDelete);
            }
            // 如果是DataTable, 使用 rowToDelete.DataGridView.Rows.Remove(rowToDelete);
        }
    }
}

添加复选框列

用于实现“全选/反选”功能。

// 添加一个 DataGridViewCheckBoxColumn
DataGridViewCheckBoxColumn selectColumn = new DataGridViewCheckBoxColumn();
selectColumn.Name = "Selected";
selectColumn.HeaderText = "选择";
selectColumn.TrueValue = true;
selectColumn.FalseValue = false;
selectColumn.IndeterminateValue = null;
dataGridView1.Columns.Insert(0, selectColumn); // 插入到第一列

实现全选功能

在窗体上添加一个 CheckBox 控件,命名为 chkSelectAll

private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
{
    bool isChecked = chkSelectAll.Checked;
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        // 注意:跳过新行(如果允许用户添加)
        if (!row.IsNewRow)
        {
            row.Cells["Selected"].Value = isChecked;
        }
    }
}

获取选中的行

private void btnGetSelected_Click(object sender, EventArgs e)
{
    if (dataGridView1.SelectedRows.Count > 0)
    {
        string selectedInfo = "选中的产品:\n";
        foreach (DataGridViewRow row in dataGridView1.SelectedRows)
        {
            // 跳过用户正在编辑的新行
            if (!row.IsNewRow)
            {
                Product p = row.DataBoundItem as Product;
                if (p != null)
                {
                    selectedInfo += $"- {p.ProductName}\n";
                }
            }
        }
        MessageBox.Show(selectedInfo);
    }
    else
    {
        MessageBox.Show("没有选中任何行。");
    }
}

第五部分:性能优化

当处理大量数据(例如成千上万行)时,DataGridView 的性能可能会下降。

  1. 使用虚拟模式 (VirtualMode) 这是最有效的优化方法,启用虚拟模式后,DataGridView 不会在内存中保存所有数据,而是只在需要时(如滚动、绘制)向你的代码请求数据。

    • 设置 dataGridView1.VirtualMode = true;
    • 处理 CellValueNeeded 事件,当 DataGridView 需要某个单元格的值时,它会向你索要。
    • 处理 CellValuePushed 事件,当用户编辑单元格并确认后,DataGridView 会将新值推送给你的代码,以便你更新数据源。
  2. 延迟加载 如果数据来自数据库,不要一次性加载所有数据,可以实现分页或滚动加载。

  3. 避免在循环中频繁操作 UI 不要在一个循环中逐行添加数据到 DataGridView,最好是先准备好整个数据集(如 DataTableList<T>),然后一次性绑定。


DataGridView 是一个功能极其强大的控件,掌握它的核心用法是每个 Windows Forms 开发者的必备技能。

  • 入门:从 DataSource 属性开始,学会绑定 DataTableBindingList<T>
  • 进阶:通过属性和事件自定义外观和行为,处理用户交互。
  • 精通:掌握按钮列、复选框列等高级用法,并了解性能优化技巧。

希望这份详细的教程能帮助你熟练使用 DataGridView