private readonly int[] _mergeColumns { 0, 1 };//需要监控合并的列判断为内容相同的可以合并单元格/// summary/// 重绘单元格/// /summary/// param namesender/param/// param namee/paramprivatevoidDGV_CellPainting(objectsender,DataGridViewCellPaintingEventArgse){DataGridViewdataGridView1(DataGridView)sender;// 1. 仅处理数据行且仅处理指定的列例如第0列if(e.RowIndex0Array.IndexOf(_mergeColumns,e.ColumnIndex)0){// 获取当前单元格的值stringcurrentValuee.Value?.ToString()??string.Empty;// 判断是否为合并区域的最后一行即下一行的值不同或者已经是最后一行boolisLastRowOfMergefalse;if(e.RowIndexdataGridView1.Rows.Count-1){isLastRowOfMergetrue;// 已经是最后一行}else{stringnextValuedataGridView1.Rows[e.RowIndex1].Cells[e.ColumnIndex].Value?.ToString()??string.Empty;isLastRowOfMerge(currentValue!nextValue);}using(BrushbackColorBrushnewSolidBrush(e.CellStyle.BackColor))using(BrushforeColorBrushnewSolidBrush(e.CellStyle.ForeColor))using(PengridLinePennewPen(dataGridView1.GridColor)){// 2. 擦除原单元格背景e.Graphics.FillRectangle(backColorBrush,e.CellBounds);// 3. 绘制边框// 始终绘制右边框e.Graphics.DrawLine(gridLinePen,e.CellBounds.Right-1,e.CellBounds.Top,e.CellBounds.Right-1,e.CellBounds.Bottom-1);// 仅在合并区域的最后一行绘制下边框if(isLastRowOfMerge){e.Graphics.DrawLine(gridLinePen,e.CellBounds.Left,e.CellBounds.Bottom-1,e.CellBounds.Right-1,e.CellBounds.Bottom-1);}// 绘制上边框如果是第一行if(e.RowIndex0){e.Graphics.DrawLine(gridLinePen,e.CellBounds.Left,e.CellBounds.Top,e.CellBounds.Right-1,e.CellBounds.Top);}// 4. 绘制文本仅在合并区域的最后一行绘制并垂直居中if(isLastRowOfMerge!string.IsNullOrEmpty(currentValue)){// 计算合并跨越的行数intmergeRowCount1;for(intie.RowIndex;i0;i--){stringprevValuedataGridView1.Rows[i-1].Cells[e.ColumnIndex].Value?.ToString()??string.Empty;if(prevValuecurrentValue)mergeRowCount;elsebreak;}// 计算合并后的总高度inttotalHeighte.CellBounds.Height*mergeRowCount;// 测量文本大小以实现居中SizeFtextSizee.Graphics.MeasureString(currentValue,e.CellStyle.Font);floatxe.CellBounds.X(e.CellBounds.Width-textSize.Width)/2;floatye.CellBounds.Y-(mergeRowCount-1)*e.CellBounds.Height(totalHeight-textSize.Height)/2;e.Graphics.DrawString(currentValue,e.CellStyle.Font,foreColorBrush,x,y,StringFormat.GenericDefault);}}// 5. 标记为已处理阻止默认绘制e.Handledtrue;}}结果如下