WinForm数据展示需要用到的控件就是DataGridView,DataGridView这个"看似简单,实则复杂"的控件给无数C#开发者带来不小的困扰。 有时候想用却不知道怎么用,接下来就一步一步把这个控件的属性和方法研究明白。
正文:
一、核心属性
DataSource: 支持DataTable、DataSet、List<T>等多种数据源AutoGenerateColumns: false ReadOnly: true/false AllowUserToAddRows: false AllowUserToDeleteRows: false SelectionMode: FullRowSelect
二、操作方法
dataGridView.Columns.Add() dataGridView.Columns.Remove() dataGridView.Columns.Clear() dataGridView.Refresh()
了解了上面的属性和方法以后,就可以开始测试使用了,下面看一个简单的用法;
namespace AccessOperate{
public partial class DgvDisplay : Form { public DgvDisplay() { InitializeComponent(); DataGridView dgv = new DataGridView(); this.Controls.Add(dgv);
dgv.AutoGenerateColumns = false; dgv.AllowUserToAddRows = false; dgv.Dock = DockStyle.Fill; dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
CreateColumns(dgv);
BindData(dgv);
} private void CreateColumns(DataGridView dgv) { var nameColumn = new DataGridViewTextBoxColumn { DataPropertyName = "Name", HeaderText = "姓名", AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill }; dgv.Columns.Add(nameColumn);
var ageColumn = new DataGridViewTextBoxColumn { DataPropertyName = "Age", HeaderText = "年龄", Width = 80 }; dgv.Columns.Add(ageColumn);
var cityColumn = new DataGridViewTextBoxColumn { DataPropertyName = "City", HeaderText = "城市", AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill }; dgv.Columns.Add(cityColumn); } private void BindData(DataGridView dgv) { var people = new List<Person> { new Person { Name = "雷军", Age = 28, City = "北京" }, new Person { Name = "马云", Age = 35, City = "杭州" }, new Person { Name = "马化腾", Age = 42, City = "广州" } }; dgv.DataSource = people; } } public class Person { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } }}
很简单,就创建一个空白的WinForm窗体,不用往里面添加DataGridView控件,这里是在用程序添加的,this.Controls.Add(dgv);
1.DataPropertyName必须与模型属性名完全一致2.设置AutoGenerateColumns = false避免列重复3.使用AutoSizeMode.Fill让列自适应宽度到这里我们就基本会使用DataGridView了,不过有时候数据不会这么简单,有时候要做的刷新和数据表的编辑,这样就需要下一定功夫了,下面接着看怎么操作;namespace AccessOperate{
public partial class DgvDisplay : Form { private List<Person> people; public DgvDisplay() { InitializeComponent(); InitializeForm(); LoadSampleData();
} private void InitializeForm() { dgv_Display.ReadOnly = false;
dgv_Display.CellValueChanged += OnCellValueChanged;
dgv_Display.CellEndEdit += OnCellEndEdit;
dgv_Display.CellBeginEdit += OnCellBeginEdit;
dgv_Display.DataError += OnDataError;
dgv_Display.UserDeletingRow += OnUserDeletingRow; } private void LoadSampleData() { people = new List<Person> { new Person { Name = "雷军", Age = 25, City = "北京", Email = "leijun@email.com", CreateDate = DateTime.Now.AddDays(-10) }, new Person { Name = "马云", Age = 30, City = "杭州", Email = "mayun@email.com", CreateDate = DateTime.Now.AddDays(-5) }, new Person { Name = "马化腾", Age = 28, City = "广州", Email = "mahuateng@email.com", CreateDate = DateTime.Now.AddDays(-3) }, new Person { Name = "王传福", Age = 35, City = "深圳", Email = "wangchuanfu@email.com", CreateDate = DateTime.Now.AddDays(-1) } }; dgv_Display.DataSource = people;
SetupColumns(); } private void SetupColumns() { if (dgv_Display.Columns.Count > 0) { dgv_Display.Columns["Name"].HeaderText = "姓名"; dgv_Display.Columns["Age"].HeaderText = "年龄"; dgv_Display.Columns["City"].HeaderText = "城市"; dgv_Display.Columns["Email"].HeaderText = "邮箱"; dgv_Display.Columns["CreateDate"].HeaderText = "创建时间";
dgv_Display.Columns["Name"].FillWeight = 20; dgv_Display.Columns["Age"].FillWeight = 15; dgv_Display.Columns["City"].FillWeight = 20; dgv_Display.Columns["Email"].FillWeight = 25; dgv_Display.Columns["CreateDate"].FillWeight = 20;
dgv_Display.Columns["CreateDate"].ReadOnly = true;
dgv_Display.Columns["Age"].ValueType = typeof(int); } } private void OnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0) return;
var dgv = sender as DataGridView; if (dgv.DataSource is List<Person> people && e.RowIndex < people.Count) { Person updatedPerson = people[e.RowIndex];
SavePersonToDatabase(updatedPerson);
this.Text = $"可编辑数据表格 - 已更新:{updatedPerson.Name} 的信息 [{DateTime.Now:HH:mm:ss}]"; } }
private void OnCellEndEdit(object sender, DataGridViewCellEventArgs e) { var dgv = sender as DataGridView; var cell = dgv[e.ColumnIndex, e.RowIndex];
string columnName = dgv.Columns[e.ColumnIndex].Name;
switch (columnName) { case "Age": if (!int.TryParse(cell.Value?.ToString(), out int age) || age < 0 || age > 150) { MessageBox.Show("请输入有效的年龄(0-150)!", "数据验证", MessageBoxButtons.OK, MessageBoxIcon.Warning); cell.Value = 0; } break;
case "Email": string email = cell.Value?.ToString(); if (!string.IsNullOrEmpty(email) && !IsValidEmail(email)) { MessageBox.Show("请输入有效的邮箱格式!", "数据验证", MessageBoxButtons.OK, MessageBoxIcon.Warning); cell.Value = ""; } break;
case "Name": if (string.IsNullOrWhiteSpace(cell.Value?.ToString())) { MessageBox.Show("姓名不能为空!", "数据验证", MessageBoxButtons.OK, MessageBoxIcon.Warning); cell.Value = "未命名"; } break; } }
private void OnCellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) { var dgv = sender as DataGridView; string columnName = dgv.Columns[e.ColumnIndex].Name;
if (columnName == "CreateDate") { e.Cancel = true; MessageBox.Show("创建时间不可编辑!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void OnDataError(object sender, DataGridViewDataErrorEventArgs e) { MessageBox.Show($"数据错误:{e.Exception.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); e.Cancel = true; } private void OnUserDeletingRow(object sender, DataGridViewRowCancelEventArgs e) { if (MessageBox.Show("确定要删除这条记录吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { e.Cancel = true; } } private void RefreshDataSource() { dgv_Display.DataSource = null; dgv_Display.DataSource = people; SetupColumns(); } private bool IsValidEmail(string email) { try { var addr = new System.Net.Mail.MailAddress(email); return addr.Address == email; } catch { return false; } } private void SavePersonToDatabase(Person person) { try { Console.WriteLine($"保存数据:{person.Name}, {person.Age}, {person.City}, {person.Email}");
Task.Run(() => { System.Threading.Thread.Sleep(100); });
} catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void BtnAdd_Click(object sender, EventArgs e) { people.Add(new Person { Name = "新用户", Age = 30, City = "上海", Email = "new@email.com", CreateDate = DateTime.Now });
RefreshDataSource(); }
private void BtnDelete_Click(object sender, EventArgs e) { if (dgv_Display.SelectedRows.Count > 0) { var selectedIndex = dgv_Display.SelectedRows[0].Index; if (selectedIndex < people.Count) { if (MessageBox.Show("确定要删除选中的记录吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { people.RemoveAt(selectedIndex); RefreshDataSource(); } } } else { MessageBox.Show("请先选择要删除的行!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
private void BtnSaveAll_Click(object sender, EventArgs e) { try { foreach (var person in people) { SavePersonToDatabase(person); } MessageBox.Show($"成功保存 {people.Count} 条记录!", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show($"批量保存失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void DgvDisplay_FormClosed(object sender, FormClosedEventArgs e) { if (dgv_Display != null) { dgv_Display.CellValueChanged -= OnCellValueChanged; dgv_Display.CellEndEdit -= OnCellEndEdit; dgv_Display.CellBeginEdit -= OnCellBeginEdit; dgv_Display.DataError -= OnDataError; dgv_Display.UserDeletingRow -= OnUserDeletingRow; } } }
public class Person { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } public string Email { get; set; } public DateTime CreateDate { get; set; } }}
1.同时监听CellValueChanged和CellEndEdit事件
总结:
DataGridView虽然功能强大,但掌握了正确的使用方法,它就会成为你开发WinForm应用的得力助手。实践是最好的老师,初学者朋友建议大家把这些代码在自己的项目中跑一遍,相信会有更深的理解。DataGridView控件还能绑定数据源,操作数据库文件,这些在后面慢慢掌握。
阅读原文:原文链接
该文章在 2026/1/22 13:20:01 编辑过