在 WinForm 中,DataGridView
是功能最强大的表格控件之一,用于显示、编辑、操作结构化数据(如数据库表、集合、DataTable 等)。它支持自定义列类型、数据绑定、单元格编辑、排序、筛选等功能,是数据管理类应用(如管理系统、数据报表)的核心控件。
一、控件核心功能与特点
-
支持多种数据来源:可绑定
DataTable
、List<T>
、数据库查询结果等; -
灵活的列类型:内置文本列、复选框列、下拉框列、按钮列等,也可自定义列;
-
丰富的交互:支持单元格编辑、行选择、排序、筛选、复制粘贴等;
-
高度可定制:可自定义样式(颜色、字体)、单元格行为、编辑规则等。
二、核心属性与事件(表格整理)
类别 | 名称 | 说明 |
---|---|---|
数据绑定 | DataSource | 绑定的数据源(如DataTable 、List<T> 、BindingSource 等) |
DataMember | 当数据源包含多个列表时,指定要显示的列表名称 | |
AutoGenerateColumns | 是否自动根据数据源生成列(默认true ,false 时需手动添加列) | |
交互控制 | AllowUserToAddRows | 是否允许用户添加新行(默认true ,最后一行显示 “*” 表示可添加) |
AllowUserToDeleteRows | 是否允许用户删除行(默认false ) | |
ReadOnly | 整个控件是否只读(true 时禁止编辑所有单元格) | |
MultiSelect | 是否允许选择多行(默认true ,false 时仅能选择一行) | |
SelectionMode | 选择模式(如FullRowSelect 整行选择、CellSelect 单元格选择等) | |
外观样式 | RowHeadersVisible | 是否显示行标题(左侧的行号列,默认true ) |
ColumnHeadersVisible | 是否显示列标题(表头,默认true ) | |
AlternatingRowsDefaultCellStyle | 交替行的样式(用于区分相邻行,如隔行变色) | |
DefaultCellStyle | 单元格默认样式(字体、颜色、对齐方式等) | |
核心事件 | CellClick | 点击单元格时触发(可获取点击的单元格位置和值) |
CellValueChanged | 单元格值修改后触发(用于实时保存或校验) | |
RowHeaderMouseClick | 点击行标题(行号)时触发(常用于选择行操作) | |
CellValidating | 单元格失去焦点时触发(用于输入校验,如限制数值范围、格式等) | |
DataBindingComplete | 数据绑定完成后触发(用于绑定后初始化样式或数据) |
三、基础用法:绑定数据并显示
场景:展示学生信息列表
从工具箱中拉入事件
可以通过右键点击属性进行列添加,也可以直接点击dataGridView 控件上的箭头进行编辑
自定义样式(交替行颜色、表头样式)
再添加列的时候,可以添加不同样式的表格属性
1. 界面设计
在窗体中添加DataGridView
控件(命名为dataGridView1
),可适当调整大小以显示完整内容。
2. 代码实现(绑定 DataTable)
using System; using System.Data; using System.Windows.Forms; namespace DataGridViewDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); // 初始化表格 InitDataGridView(); // 绑定数据 BindData(); } private void InitDataGridView() { // 不自动生成列(手动定义列更灵活) dataGridView1.AutoGenerateColumns = false; // 1. 添加ID列(文本列) DataGridViewTextBoxColumn idColumn = new DataGridViewTextBoxColumn(); idColumn.Name = "ID"; // 列名(用于关联数据字段) idColumn.HeaderText = "学号"; // 表头显示文本 idColumn.DataPropertyName = "ID"; // 绑定的数据源字段名 idColumn.Width = 80; dataGridView1.Columns.Add(idColumn); // 2. 添加姓名列(文本列) DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn(); nameColumn.Name = "Name"; nameColumn.HeaderText = "姓名"; nameColumn.DataPropertyName = "Name"; nameColumn.Width = 100; dataGridView1.Columns.Add(nameColumn); // 3. 添加年龄列(文本列,限制为数字) DataGridViewTextBoxColumn ageColumn = new DataGridViewTextBoxColumn(); ageColumn.Name = "Age"; ageColumn.HeaderText = "年龄"; ageColumn.DataPropertyName = "Age"; ageColumn.Width = 60; dataGridView1.Columns.Add(ageColumn); // 4. 添加是否住校列(复选框列) DataGridViewCheckBoxColumn boardColumn = new DataGridViewCheckBoxColumn(); boardColumn.Name = "IsBoarding"; boardColumn.HeaderText = "是否住校"; boardColumn.DataPropertyName = "IsBoarding"; boardColumn.Width = 80; dataGridView1.Columns.Add(boardColumn); // 其他设置:整行选择、禁止删除行、允许添加行 dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView1.AllowUserToDeleteRows = false; dataGridView1.AllowUserToAddRows = true; } // 绑定数据到表格 private void BindData() { // 创建数据源(DataTable) DataTable dt = new DataTable(); // 添加与表格列对应的字段 dt.Columns.Add("ID", typeof(int)); dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Age", typeof(int)); dt.Columns.Add("IsBoarding", typeof(bool)); // 添加示例数据 dt.Rows.Add(101, "张三", 18, true); dt.Rows.Add(102, "李四", 19, false); dt.Rows.Add(103, "王五", 17, true); // 绑定数据源 dataGridView1.DataSource = dt; } } }
四、进阶用法与场景
1. 绑定自定义对象集合(List<T>)
除了DataTable
,DataGridView
也可直接绑定到自定义类的集合,更适合面向对象开发:
// 定义学生类 public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public bool IsBoarding { get; set; } } // 绑定List<Student>到表格 private void BindListData() { List<Student> students = new List<Student> { new Student { ID = 101, Name = "张三", Age = 18, IsBoarding = true }, new Student { ID = 102, Name = "李四", Age = 19, IsBoarding = false } }; dataGridView1.DataSource = students; }
2. 单元格编辑与校验(如限制年龄范围)
通过CellValidating
事件校验输入,确保年龄在 1-100 之间:
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { // 仅校验“年龄”列(索引为2,对应前面定义的ageColumn) if (dataGridView1.Columns[e.ColumnIndex].Name == "Age") { // 尝试将输入转换为整数 if (!int.TryParse(e.FormattedValue.ToString(), out int age) || age < 1 || age > 100) { // 校验失败:提示并取消编辑 e.Cancel = true; // 阻止焦点离开单元格 dataGridView1.Rows[e.RowIndex].ErrorText = "年龄必须是1-100之间的数字"; } else { // 校验成功:清除错误提示 dataGridView1.Rows[e.RowIndex].ErrorText = ""; } } }
3. 获取选中行数据(如双击行查看详情)
通过CellDoubleClick
事件获取选中行的数据:
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { // 忽略标题行(行索引≥0) if (e.RowIndex < 0) return; // 获取选中行 DataGridViewRow selectedRow = dataGridView1.Rows[e.RowIndex]; // 读取行中各列的值(根据列名或索引) int id = (int)selectedRow.Cells["ID"].Value; string name = selectedRow.Cells["Name"].Value.ToString(); int age = (int)selectedRow.Cells["Age"].Value; bool isBoarding = (bool)selectedRow.Cells["IsBoarding"].Value; // 显示详情 MessageBox.Show($"选中学生:\nID:{id}\n姓名:{name}\n年龄:{age}\n是否住校:{isBoarding}"); }
4. 自定义样式(交替行颜色、表头样式)
通过样式设置提升表格可读性:
private void SetGridViewStyle() { // 表头样式:蓝色背景、白色文字、居中对齐 dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.SteelBlue; dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.White; dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; // 单元格样式:居中对齐 dataGridView1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; // 交替行颜色(隔行变色) dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.LightGray; // 取消默认选中样式(避免蓝色高亮) dataGridView1.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.LightBlue; }
5. 动态添加 / 删除行
// 添加新行(假设数据源是DataTable) private void btnAddRow_Click(object sender, EventArgs e) { if (dataGridView1.DataSource is DataTable dt) { dt.Rows.Add(104, "赵六", 20, true); // 新增一行数据 } } // 删除选中行 private void btnDeleteRow_Click(object sender, EventArgs e) { if (dataGridView1.SelectedRows.Count > 0 && dataGridView1.SelectedRows[0].Index != dataGridView1.NewRowIndex) { dataGridView1.Rows.RemoveAt(dataGridView1.SelectedRows[0].Index); } else { MessageBox.Show("请选择要删除的行!"); } }
五、常见问题与解决方案
1. 数据不显示
-
原因:
-
未设置
DataSource
或数据源为空; -
AutoGenerateColumns = false
但未手动添加列,或DataPropertyName
与数据源字段不匹配。
-
-
解决:检查数据源是否有效,确保列的
DataPropertyName
与数据源字段名一致。
2. 编辑后数据未保存到数据源
-
原因:
DataGridView
默认实时更新绑定的数据源(如DataTable
),但需确保数据源支持修改(如List<T>
需实现INotifyPropertyChanged
接口)。 -
解决:若使用
List<T>
,让实体类实现INotifyPropertyChanged
以触发数据更新。
3. 列宽 / 行高自适应内容
设置列宽自动适应内容:
// 列宽自适应内容(包括表头和单元格) dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; // 行高自适应内容 dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
4. 排序功能失效
-
原因:默认仅对
DataTable
、BindingSource
等支持排序的数据源有效,List<T>
需手动实现排序。 -
解决
:使用BindingSource包装List<T>,并启用排序:
BindingSource bs = new BindingSource(); bs.DataSource = students; bs.Sort = "Age ASC"; // 按年龄升序 dataGridView1.DataSource = bs;
六、适用场景总结
场景类型 | 实现方式 | 示例 |
---|---|---|
数据库数据展示 | 绑定DataTable (从数据库查询) | 展示客户列表、订单记录 |
可编辑的数据表格 | 启用AllowUserToAddRows + 编辑校验 | 学生信息录入、商品信息修改 |
数据筛选与排序 | 结合BindingSource 实现 | 按条件筛选数据、按列排序 |
复杂交互表格 | 自定义列(下拉框、按钮)+ 事件处理 | 带操作按钮的列表(查看 / 编辑 / 删除) |
总结
DataGridView
是 WinForm 中处理表格数据的核心控件,通过灵活的数据绑定、自定义列类型和事件处理,可满足从简单数据展示到复杂交互编辑的各种需求。使用时需注意数据源匹配、编辑校验和样式优化,以提升数据管理效率和用户体验。