如何在C# WinForm的DataGridView中显示JSON字符串并实现单元格合并
在C# WinForms DataGridView中实现JSON显示+单元格合并
嘿,看起来你已经搞定了JSON数据在DataGridView的基础显示,接下来要实现重复单元格的合并功能对吧?我来给你一步步拆解实现方案,直接上手就能用~
第一步:完善JSON数据的绑定(确保数据正确加载)
首先,咱们先把你的JSON字符串正确反序列化成实体类并绑定到DataGridView,这样后续合并逻辑更清晰。
1. 定义实体类
先创建一个和JSON字段对应的实体类:
public class ProjectInfo { public string Company { get; set; } public string ProjectName { get; set; } public string Developer { get; set; } public int Hour { get; set; } public int Overtime { get; set; } public string Contribution { get; set; } }
2. 反序列化JSON并绑定到DataGridView
更新你的Form1_Load方法,用Newtonsoft.Json(最常用的JSON处理库)来解析JSON:
private void Form1_Load(object sender, EventArgs e) { // 你的JSON字符串(注意把单引号换成双引号,符合JSON标准格式) string myDynamicJSON = @"[ { 'Company': 'Company A', 'ProjectName': 'Project A', 'Developer': 'No developer assigned', 'Hour': 0, 'Overtime': 0, 'Contribution': '0' }, { 'Company': 'Company A', 'ProjectName': 'Project B', 'Developer': 'paul', 'Hour': 8, 'Overtime': 2, 'Contribution': '100%' }, { 'Company': 'Company B', 'ProjectName': 'Project X', 'Developer': 'john', 'Hour': 7, 'Overtime': 1, 'Contribution': '90%' } ]"; // 替换单引号为双引号,避免JSON解析报错 myDynamicJSON = myDynamicJSON.Replace("'", "\""); // 反序列化为实体列表 var projectList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ProjectInfo>>(myDynamicJSON); // 绑定到DataGridView dataGridView1.DataSource = projectList; // 可选:关闭自动添加行,避免空行干扰合并 dataGridView1.AllowUserToAddRows = false; }
提示:如果你的项目还没装Newtonsoft.Json,打开NuGet包管理器,搜索
Newtonsoft.Json安装即可。
第二步:实现单元格合并核心逻辑
咱们通过隐藏重复单元格+扩展上一个单元格的行跨度来实现合并,同时处理单元格绘制让内容居中显示。
1. 编写合并单元格的方法
这个方法会遍历指定列,把相邻值相同的单元格合并:
// 合并指定列的重复单元格 private void MergeCells(DataGridView dgv, int columnIndex) { if (dgv.Rows.Count == 0) return; DataGridViewCell prevCell = dgv.Rows[0].Cells[columnIndex]; for (int i = 1; i < dgv.Rows.Count; i++) { DataGridViewCell currentCell = dgv.Rows[i].Cells[columnIndex]; // 判断当前单元格和上一个单元格值是否相同(处理null情况) bool valuesMatch = false; if (prevCell.Value != null && currentCell.Value != null) { valuesMatch = prevCell.Value.ToString().Equals(currentCell.Value.ToString(), StringComparison.OrdinalIgnoreCase); } else if (prevCell.Value == null && currentCell.Value == null) { valuesMatch = true; } if (valuesMatch) { // 隐藏当前单元格 currentCell.Visible = false; // 增加上一个单元格的行跨度 prevCell.RowSpan++; } else { // 更新上一个单元格为当前单元格,继续遍历 prevCell = currentCell; } } }
2. 在数据绑定完成后调用合并方法
当DataGridView绑定完数据后,触发合并逻辑。咱们可以绑定DataBindingComplete事件:
public Form1() { InitializeComponent(); // 绑定事件 dataGridView1.DataBindingComplete += dataGridView1_DataBindingComplete; dataGridView1.CellPainting += dataGridView1_CellPainting; } private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { // 合并Company列(索引为0) MergeCells(dataGridView1, 0); // 如果需要合并ProjectName列,只需再加一行: // MergeCells(dataGridView1, 1); }
3. 处理单元格绘制,让合并内容居中
默认情况下,合并后的单元格内容会显示在顶部,咱们通过CellPainting事件调整为居中:
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // 跳过表头和无效行 if (e.RowIndex < 0 || e.ColumnIndex < 0) return; DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]; // 如果是合并的单元格(行跨度>1且可见),自定义绘制 if (cell.Visible && cell.RowSpan > 1) { // 绘制单元格背景 e.Paint(e.CellBounds, DataGridViewPaintParts.Background); // 设置内容居中格式 StringFormat sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; // 绘制单元格文本 e.Graphics.DrawString( cell.Value?.ToString() ?? string.Empty, e.CellStyle.Font, Brushes.Black, e.CellBounds, sf); // 绘制单元格边框 e.Paint(e.CellBounds, DataGridViewPaintParts.Border); // 取消默认绘制逻辑 e.Handled = true; } }
第三步:处理排序后的重新合并(可选)
如果你的DataGridView允许用户点击表头排序,排序后需要重新执行合并逻辑,否则合并效果会混乱。咱们绑定ColumnHeaderMouseClick事件:
// 在Form构造函数里添加事件绑定 dataGridView1.ColumnHeaderMouseClick += dataGridView1_ColumnHeaderMouseClick; private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { var projectList = (List<ProjectInfo>)dataGridView1.DataSource; var columnName = dataGridView1.Columns[e.ColumnIndex].Name; // 根据点击的列排序 projectList = columnName switch { nameof(ProjectInfo.Company) => projectList.OrderBy(x => x.Company).ToList(), nameof(ProjectInfo.ProjectName) => projectList.OrderBy(x => x.ProjectName).ToList(), nameof(ProjectInfo.Hour) => projectList.OrderBy(x => x.Hour).ToList(), _ => projectList.OrderBy(x => x.Company).ToList() }; // 重新绑定数据源 dataGridView1.DataSource = projectList; // 重新合并单元格 MergeCells(dataGridView1, 0); }
这样一来,你的DataGridView就能完美显示JSON数据,并且自动合并相同的单元格啦~
内容的提问来源于stack exchange,提问作者Sachith Wickramaarachchi
相关产品推荐
相关产品推荐

