ASP.net下實現合并單元格相對簡單,很大程度上是因為基於HTML;Winform下的DataGridView實現比較繁瑣,目前看似只有重繪這條路;如果嫌累可以使用Developer Express .NET的全套解決方案;
[轉載]二维表头的实现,來源不明
int top = 0;
int left = 0;
int height = 0;
int width1 = 0;
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
#region 重绘datagridview表头
DataGridView dgv = (DataGridView)(sender);
if (e.RowIndex == -1 && (e.ColumnIndex == 3 || e.ColumnIndex == 4))
{
//e.CellStyle.Font = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Bold);
//e.CellStyle.WrapMode = DataGridViewTriState.True;
if (e.ColumnIndex == 3)
{
top = e.CellBounds.Top;
left = e.CellBounds.Left;
height = e.CellBounds.Height;
width1 = e.CellBounds.Width;
}
int width2 = this.dataGridView1.Columns[4].Width;
Rectangle rect = new Rectangle(left, top, width1 + width2, e.CellBounds.Height);
using (Brush backColorBrush = new SolidBrush(e.CellStyle.BackColor))
{
//抹去原来的cell背景
e.Graphics.FillRectangle(backColorBrush, rect);
}
using (Pen gridLinePen = new Pen(dgv.GridColor))
{
e.Graphics.DrawLine(gridLinePen, left, top, left + width1 + width2, top);
e.Graphics.DrawLine(gridLinePen, left, top + height / 2, left + width1 + width2, top + height /
2);
e.Graphics.DrawLine(gridLinePen, left + width1, top + height / 2, left + width1, top + height);
//计算绘制字符串的位置
string columnValue = "Year";
SizeF sf = e.Graphics.MeasureString(columnValue, e.CellStyle.Font);
float lstr = (width1 + width2 - sf.Width) / 2;
float rstr = (height / 2 - sf.Height) / 2;
//画出文本框
if (columnValue != "")
{
e.Graphics.DrawString(columnValue, e.CellStyle.Font,
new SolidBrush(e.CellStyle.ForeColor),
left + lstr,
top + rstr,
StringFormat.GenericDefault);
}
//计算绘制字符串的位置
columnValue = "局网台资产额";
sf = e.Graphics.MeasureString(columnValue, e.CellStyle.Font);
lstr = (width1 - sf.Width) / 2;
rstr = (height / 2 - sf.Height) / 2;
//画出文本框
if (columnValue != "")
{
e.Graphics.DrawString(columnValue, e.CellStyle.Font,
new SolidBrush(e.CellStyle.ForeColor),
left + lstr,
top + height / 2 + rstr,
StringFormat.GenericDefault);
}
//计算绘制字符串的位置
columnValue = "网络资产额";
sf = e.Graphics.MeasureString(columnValue, e.CellStyle.Font);
lstr = (width2 - sf.Width) / 2;
rstr = (height / 2 - sf.Height) / 2;
//画出文本框
if (columnValue != "")
{
e.Graphics.DrawString(columnValue, e.CellStyle.Font,
new SolidBrush(e.CellStyle.ForeColor),
left + width1 + lstr,
top + height / 2 + rstr,
StringFormat.GenericDefault);
}
}
e.Handled = true;
}
#endregion
}
http://www.cnblogs.com/liuke209/archive/2006/07/29/463023.html
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
namespace OPSS.Logic.Checks
{
/// <summary>
/// 对DataGridView进行合并操作的类
/// </summary>
public class DGVOper
{
private static SortedList rowSpan = new SortedList();//取得需要重新绘制的单元格
private static string rowValue = "";//重新绘制的文本框内容
#region 单元格绘制
/// <summary>
///
/// DataGridView合并单元格(横向)
/// </summary>
/// <param name="dgv">绘制的DataGridview </param>
/// <param name="cellArgs">绘制单元格的参数(DataGridview的CellPainting事件中参数)</param>
/// <param name="minColIndex">起始单元格在DataGridView中的索引号</param>
/// <param name="maxColIndex">结束单元格在DataGridView中的索引号</param>
public static void MerageRowSpan(DataGridView dgv, DataGridViewCellPaintingEventArgs cellArgs, int minColIndex, int maxColIndex)
{
if (cellArgs.ColumnIndex < minColIndex || cellArgs.ColumnIndex > maxColIndex) return;
Rectangle rect=new Rectangle();
using (Brush gridBrush = new SolidBrush(dgv.GridColor),
backColorBrush = new SolidBrush(cellArgs.CellStyle.BackColor))
{
//抹去原来的cell背景
cellArgs.Graphics.FillRectangle(backColorBrush, cellArgs.CellBounds);
}
cellArgs.Handled = true;
if (rowSpan[cellArgs.ColumnIndex] == null)
{
//首先判断当前单元格是不是需要重绘的单元格
//保留此单元格的信息,并抹去此单元格的背景
rect.X = cellArgs.CellBounds.X;
rect.Y = cellArgs.CellBounds.Y;
rect.Width = cellArgs.CellBounds.Width;
rect.Height = cellArgs.CellBounds.Height;
rowValue += cellArgs.Value.ToString();
rowSpan.Add(cellArgs.ColumnIndex, rect);
if (cellArgs.ColumnIndex != maxColIndex)
return;
MeragePrint(dgv, cellArgs, minColIndex, maxColIndex);
}
else
{
IsPostMerage(dgv, cellArgs, minColIndex, maxColIndex);
}
}
/// <summary>
/// 不是初次单元格绘制
/// </summary>
/// <param name="dgv"></param>
/// <param name="cellArgs"></param>
/// <param name="minColIndex"></param>
/// <param name="maxColIndex"></param>
public static void IsPostMerage(DataGridView dgv, DataGridViewCellPaintingEventArgs cellArgs, int minColIndex, int maxColIndex)
{
//比较单元是否有变化
Rectangle rectArgs = (Rectangle)rowSpan[cellArgs.ColumnIndex];
if (rectArgs.X != cellArgs.CellBounds.X || rectArgs.Y != cellArgs.CellBounds.Y
|| rectArgs.Width != cellArgs.CellBounds.Width || rectArgs.Height != cellArgs.CellBounds.Height)
{
rectArgs.X = cellArgs.CellBounds.X;
rectArgs.Y = cellArgs.CellBounds.Y;
rectArgs.Width = cellArgs.CellBounds.Width;
rectArgs.Height = cellArgs.CellBounds.Height;
rowSpan[cellArgs.ColumnIndex] = rectArgs;
}
MeragePrint(dgv,cellArgs,minColIndex,maxColIndex);
}
//画制单元格
private static void MeragePrint(DataGridView dgv, DataGridViewCellPaintingEventArgs cellArgs, int minColIndex, int maxColIndex)
{
int width = 0;//合并后单元格总宽度
int height = cellArgs.CellBounds.Height;//合并后单元格总高度
for (int i = minColIndex; i <= maxColIndex;i++ )
{
width += ((Rectangle)rowSpan[i]).Width;
}
Rectangle rectBegin = (Rectangle)rowSpan[minColIndex];//合并第一个单元格的位置信息
Rectangle rectEnd = (Rectangle)rowSpan[maxColIndex];//合并最后一个单元格的位置信息
//合并单元格的位置信息
Rectangle reBounds = new Rectangle();
reBounds.X = rectBegin.X;
reBounds.Y = rectBegin.Y;
reBounds.Width = width - 1;
reBounds.Height = height - 1;
using (Brush gridBrush = new SolidBrush(dgv.GridColor),
backColorBrush = new SolidBrush(cellArgs.CellStyle.BackColor))
{
using (Pen gridLinePen = new Pen(gridBrush))
{
// 画出上下两条边线,左右边线无
Point blPoint = new Point(rectBegin.Left, rectBegin.Bottom - 1);//底线左边位置
Point brPoint = new Point(rectEnd.Right - 1, rectEnd.Bottom - 1);//底线右边位置
cellArgs.Graphics.DrawLine(gridLinePen, blPoint, brPoint);//下边线
Point tlPoint = new Point(rectBegin.Left, rectBegin.Top);//上边线左边位置
Point trPoint = new Point(rectEnd.Right - 1, rectEnd.Top);//上边线右边位置
cellArgs.Graphics.DrawLine(gridLinePen, tlPoint, trPoint); //上边线
Point ltPoint = new Point(rectBegin.Left, rectBegin.Top);//左边线顶部位置
Point lbPoint = new Point(rectBegin.Left, rectBegin.Bottom - 1);//左边线底部位置
cellArgs.Graphics.DrawLine(gridLinePen, ltPoint, lbPoint); //左边线
Point rtPoint = new Point(rectEnd.Right - 1, rectEnd.Top);//右边线顶部位置
Point rbPoint = new Point(rectEnd.Right - 1, rectEnd.Bottom - 1);//右边线底部位置
cellArgs.Graphics.DrawLine(gridLinePen, rtPoint, rbPoint); //右边线
//计算绘制字符串的位置
SizeF sf = cellArgs.Graphics.MeasureString(rowValue, cellArgs.CellStyle.Font);
float lstr = (width - sf.Width) / 2;
float rstr = (height - sf.Height) / 2;
//画出文本框
if (rowValue != "")
{
cellArgs.Graphics.DrawString(rowValue, cellArgs.CellStyle.Font,
new SolidBrush(cellArgs.CellStyle.ForeColor),
rectBegin.Left + lstr,
rectBegin.Top + rstr,
StringFormat.GenericDefault);
}
}
cellArgs.Handled = true;
}
}
#endregion
}
}
=======================================================
在DataGridView页面的DataGridView的CellPainting事件中写下下面代码就OK了
#region 统计行单元格绘制
private void dgConfirm_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex!=-1 && dgConfirm.Rows[e.RowIndex].Cells[1].Value.ToString()==" " )
{
e.CellStyle.Font = new Font(dgConfirm.DefaultCellStyle.Font, FontStyle.Bold);
e.CellStyle.WrapMode = DataGridViewTriState.True;
DGVOper.MerageRowSpan(dgConfirm, e, 1, 2);
}
//重绘统计行的选择框背景
if ((e.RowIndex == dgConfirm.Rows.Count - 1) && (e.ColumnIndex==0))
{
Rectangle rect = new Rectangle();
rect.X = e.CellBounds.X;
rect.Y = e.CellBounds.Y;
rect.Width = e.CellBounds.Width;
rect.Height = e.CellBounds.Height;
e.Paint(rect,DataGridViewPaintParts.ContentBackground);
e.PaintBackground(rect,false);
e.Handled = true;
}
}
#endregion
怎么样效果行吗?但是沒有時間垂直合并的