DataGridView合并单元格,重绘后选中内容被覆盖的解决办法
DataGridView合并单元格只能进行重绘,网上基本上使用的是下面的方法:
1 /// <summary> 2 /// 说明:纵向合并单元格 3 /// 参数:dgv DataGridView,e 绘制的单元格 4 /// </summary> 5 public void MergeCell(DataGridView dgv, DataGridViewCellPaintingEventArgs e) 6 { 7 int x = e.RowIndex, y = e.ColumnIndex; 8 using (Brush gridBrush = new SolidBrush(dgv.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor)) 9 { 10 using (Pen gridLinePen = new Pen(gridBrush)) 11 { 12 // 擦除原单元格 13 e.Graphics.FillRectangle(backColorBrush, e.CellBounds); 14 ////绘制单元格相互间隔的区分线条, datagridview自己会处理左侧和上边缘的线条 15 bool b = false; 16 if (x == dgv.RowCount - 1) 17 b = true; 18 else 19 if (e.Value.ToString() != dgv.Rows[x + 1].Cells[y].Value.ToString()) 20 b = true; 21 if (b) 22 { 23 //下边缘的线 24 e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); 25 int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height; 26 int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width; 27 int cellheight = e.CellBounds.Height; 28 int cellwidth = e.CellBounds.Width; 29 int countRows = 1; //计算合并单元格的总行数,以便内容可以居中显示 30 for (int i = x; i > 0; i--) 31 { 32 if (dgv.Rows[i - 1].Cells[y].Value.ToString() == e.Value.ToString()) 33 countRows++; 34 else 35 break; 36 } 37 //绘制值 38 e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (countRows - 1) + (cellheight * countRows - fontheight) / 2, StringFormat.GenericDefault); 39 } 40 //右侧的线 41 e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); 42 //设置处理事件完成(关键点),只有设置为ture,才能显示出想要的结果 43 e.Handled = true; 44 } 45 } 46 }
通过重绘可以达到合并单元格的目的,可是内容不居中很难看,居中的话又会出现点问题,如果选中重绘时擦除的单元格,内容会被覆盖,想了各种办法修改以上代码都无法解决。
最终另辟蹊径,不重绘单元格,而是新建Label覆盖到单元格上,达到合并单元格的假象,对DataGridView不作任何处理,这样就不会出现内容显示的问题了(唯一存在的问题就是合并的单元格无法被选中了),代码如下:
1 /// <summary> 2 /// 说明:纵向合并单元格 3 /// 参数:dgv DataGridView,e 绘制的单元格 4 /// </summary> 5 public void MergeCell(DataGridView dgv, DataGridViewCellPaintingEventArgs e) 6 { 7 int x = e.RowIndex, y = e.ColumnIndex; 8 bool b = false; 9 if (x == dgv.RowCount - 1) 10 b = true; 11 else 12 if (e.Value.ToString() != dgv.Rows[x + 1].Cells[y].Value.ToString()) 13 b = true; 14 if (b) 15 { 16 int countRows = 1;//合并单元格的总行数 17 for (int i = x; i > 0; i--) 18 { 19 if (dgv.Rows[i - 1].Cells[y].Value.ToString() == e.Value.ToString()) 20 countRows++; 21 else 22 break; 23 } 24 Rectangle cell = e.CellBounds; 25 Label newLable = new Label(); 26 newLable.BackColor = Color.White; 27 newLable.Height = cell.Height * countRows - 1; 28 newLable.Width = cell.Width - 1; 29 newLable.TextAlign = ContentAlignment.MiddleCenter; 30 newLable.Left = cell.X; 31 newLable.Top = cell.Y - (countRows - 1) * cell.Height; 32 newLable.Text = e.Value.ToString(); 33 dgv.Controls.Add(newLable); 34 } 35 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?