【Winform-自定义控件】DataGridView 单元格合并和二维表头

时间:2023-01-28 04:14:28

DataGridView单元格合并和二维表头应用:

【Winform-自定义控件】DataGridView 单元格合并和二维表头

            //DataGridView绑定数据
DataTable dt = new DataTable();
dt.Columns.Add("");
dt.Columns.Add("");
dt.Columns.Add("");
dt.Columns.Add("");
dt.Rows.Add("中国", "上海", "", "");
dt.Rows.Add("中国", "北京", "", "");
dt.Rows.Add("美国", "纽约", "", "");
dt.Rows.Add("美国", "华劢顿", "", "");
dt.Rows.Add("英国", "伦敦", "", "");
this.rowMergeView1.DataSource = dt;
//列标题高度
this.rowMergeView1.ColumnHeadersHeight = ;
//设置不能调整列标题高度
this.rowMergeView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
//合并的列(columnName)
this.rowMergeView1.MergeColumnNames.Add("Column1");
//合并的列标题,第3列起,共2列
this.rowMergeView1.AddSpanHeader(, , "性别");

自定义控件全部代码: 空间上添加一个timer1,20毫秒

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices; /// <summary>
/// DataGridView行合并.请对属性MergeColumnNames 赋值既可
/// </summary>
public partial class RowMergeView : DataGridView
{
#region 构造函数
public RowMergeView()
{
InitializeComponent();
}
#endregion
#region 重写的事件
protected override void OnPaint(PaintEventArgs pe)
{
// TODO: 在此处添加自定义绘制代码 // 调用基类 OnPaint
base.OnPaint(pe);
}
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
try
{
if (e.RowIndex > - && e.ColumnIndex > -)
{
DrawCell(e);
}
else
{
//二维表头
if (e.RowIndex == -)
{
if (SpanRows.ContainsKey(e.ColumnIndex)) //被合并的列
{
//画边框
Graphics g = e.Graphics;
e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); int left = e.CellBounds.Left, top = e.CellBounds.Top + ,
right = e.CellBounds.Right, bottom = e.CellBounds.Bottom; switch (SpanRows[e.ColumnIndex].Position)
{
case :
left += ;
break;
case :
break;
case :
right -= ;
break;
} //画上半部分底色
g.FillRectangle(new SolidBrush(this._mergecolumnheaderbackcolor), left, top,
right - left, (bottom - top) / ); //画中线
g.DrawLine(new Pen(this.GridColor), left, (top + bottom) / ,
right, (top + bottom) / ); //写小标题
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center; g.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black,
new Rectangle(left, (top + bottom) / , right - left, (bottom - top) / ), sf);
left = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Left, true).Left - ; if (left < ) left = this.GetCellDisplayRectangle(-, -, true).Width;
right = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Right, true).Right - ;
if (right < ) right = this.Width; g.DrawString(SpanRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black,
new Rectangle(left, top, right - left, (bottom - top) / ), sf);
e.Handled = true;
}
}
}
base.OnCellPainting(e);
}
catch
{ }
}
protected override void OnCellClick(DataGridViewCellEventArgs e)
{
base.OnCellClick(e);
}
#endregion
#region 自定义方法
/// <summary>
/// 画单元格
/// </summary>
/// <param name="e"></param>
private void DrawCell(DataGridViewCellPaintingEventArgs e)
{
if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet)
{
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
Brush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor);
SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
int cellwidth;
//上面相同的行数
int UpRows = ;
//下面相同的行数
int DownRows = ;
//总行数
int count = ;
if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -)
{
cellwidth = e.CellBounds.Width;
Pen gridLinePen = new Pen(gridBrush);
string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? "" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim();
if (!string.IsNullOrEmpty(curValue))
{
#region 获取下面的行数
for (int i = e.RowIndex; i < this.Rows.Count; i++)
{
if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
{
//this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected; DownRows++;
if (e.RowIndex != i)
{
cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
}
}
else
{
break;
}
}
#endregion
#region 获取上面的行数
for (int i = e.RowIndex; i >= ; i--)
{
if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
{
//this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
UpRows++;
if (e.RowIndex != i)
{
cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
}
}
else
{
break;
}
}
#endregion
count = DownRows + UpRows - ;
if (count < )
{
return;
}
}
if (this.Rows[e.RowIndex].Selected)
{
backBrush.Color = e.CellStyle.SelectionBackColor;
fontBrush.Color = e.CellStyle.SelectionForeColor;
}
//以背景色填充
e.Graphics.FillRectangle(backBrush, e.CellBounds);
//画字符串
PaintingFont(e, cellwidth, UpRows, DownRows, count);
if (DownRows == )
{
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - , e.CellBounds.Right - , e.CellBounds.Bottom - );
count = ;
}
// 画右边线
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - , e.CellBounds.Top, e.CellBounds.Right - , e.CellBounds.Bottom); e.Handled = true;
}
}
/// <summary>
/// 画字符串
/// </summary>
/// <param name="e"></param>
/// <param name="cellwidth"></param>
/// <param name="UpRows"></param>
/// <param name="DownRows"></param>
/// <param name="count"></param>
private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count)
{
SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
int cellheight = e.CellBounds.Height; if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / , e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight);
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / , e.CellBounds.Y - cellheight * (UpRows - ) + (cellheight * count - fontheight) / );
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - ) + (cellheight * count - fontheight) / );
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - ) + (cellheight * count - fontheight) / );
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / , e.CellBounds.Y - cellheight * (UpRows - ));
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - ));
}
else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight)
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - ));
}
else
{
e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / , e.CellBounds.Y - cellheight * (UpRows - ) + (cellheight * count - fontheight) / );
}
}
#endregion
#region 属性
/// <summary>
/// 设置或获取合并列的集合
/// </summary>
[MergableProperty(false)]
[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
[Localizable(true)]
[Description("设置或获取合并列的集合"), Browsable(true), Category("单元格合并")]
public List<string> MergeColumnNames
{
get
{
return _mergecolumnname;
}
set
{
_mergecolumnname = value;
}
}
private List<string> _mergecolumnname = new List<string>();
#endregion
#region 二维表头
private struct SpanInfo //表头信息
{
public SpanInfo(string Text, int Position, int Left, int Right)
{
this.Text = Text;
this.Position = Position;
this.Left = Left;
this.Right = Right;
} public string Text; //列主标题
public int Position; //位置,1:左,2中,3右
public int Left; //对应左行
public int Right; //对应右行
}
private Dictionary<int, SpanInfo> SpanRows = new Dictionary<int, SpanInfo>();//需要2维表头的列
/// <summary>
/// 合并列
/// </summary>
/// <param name="ColIndex">列的索引</param>
/// <param name="ColCount">需要合并的列数</param>
/// <param name="Text">合并列后的文本</param>
public void AddSpanHeader(int ColIndex, int ColCount, string Text)
{
if (ColCount < )
{
throw new Exception("行宽应大于等于2,合并1列无意义。");
}
//将这些列加入列表
int Right = ColIndex + ColCount - ; //同一大标题下的最后一列的索引
SpanRows[ColIndex] = new SpanInfo(Text, , ColIndex, Right); //添加标题下的最左列
SpanRows[Right] = new SpanInfo(Text, , ColIndex, Right); //添加该标题下的最右列
for (int i = ColIndex + ; i < Right; i++) //中间的列
{
SpanRows[i] = new SpanInfo(Text, , ColIndex, Right);
}
}
/// <summary>
/// 清除合并的列
/// </summary>
public void ClearSpanInfo()
{
SpanRows.Clear();
//ReDrawHead();
}
private void DataGridViewEx_Scroll(object sender, ScrollEventArgs e)
{
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)// && e.Type == ScrollEventType.EndScroll)
{
timer1.Enabled = false; timer1.Enabled = true;
}
}
//刷新显示表头
public void ReDrawHead()
{
foreach (int si in SpanRows.Keys)
{
this.Invalidate(this.GetCellDisplayRectangle(si, -, true));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
ReDrawHead();
}
/// <summary>
/// 二维表头的背景颜色
/// </summary>
[Description("二维表头的背景颜色"), Browsable(true), Category("二维表头")]
public Color MergeColumnHeaderBackColor
{
get { return this._mergecolumnheaderbackcolor; }
set { this._mergecolumnheaderbackcolor = value; }
}
private Color _mergecolumnheaderbackcolor = System.Drawing.SystemColors.Control;
#endregion
}