DataGridView合并单元格只能进行重绘,网上基本上使用的是下面的方法:
1 ///2 /// 说明:纵向合并单元格 3 /// 参数:dgv DataGridView,e 绘制的单元格 4 /// 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 else19 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 else35 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 ///2 /// 说明:纵向合并单元格 3 /// 参数:dgv DataGridView,e 绘制的单元格 4 /// 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 else12 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 else22 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 }