You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:37:09