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
}

【Winform-自定义控件】DataGridView 单元格合并和二维表头的更多相关文章

  1. 如何通过DataGridView 实现单元格合并和二维表头

    先看下实现出来的效果(这里随便写了几组数据,用来测试) 先初始一个DataGridView 设置哪几列 DataGridView 里男女这两列的 AutoSizeMode 可以设置Fill. publ ...

  2. winform中dataGridView单元格根据值设置新值,彻底解决绑定后数据类型转换的困难

    // winform中dataGridView单元格在数据绑定后,数据类型更改困难,只能迂回实现.有时候需要将数字变换为不同的文字描述,就会出现int32到string类型转换的异常,借助CellFo ...

  3. DataGridView单元格合并

    本文章转载:http://www.cnblogs.com/xiaofengfeng/p/3382094.html 图: 代码就是如此简单 文件下载:DataGridView单元格合并源码 也可以参考: ...

  4. C#实例:datagridview单元格合并

    这是替C#微信交流群群友做的一个小实例,目的就是在datagridview选择对应行以后,点击button后获取对应行的ip,并执行相应的操作,其实我觉得这样的话button没必要非放置到datagr ...

  5. winform的datagridview单元格输入限制和右键单击datagridview单元格焦点跟着改变

    在datagridview的EditingControlShowing事件里面添加代码: if (this.dgv_pch.Columns[dgv_pch.CurrentCell.ColumnInde ...

  6. [WinForm]- 设置DataGridView单元格内根据不同值显示图片

    首先设置要显示图片的列 DataGridViewImageColumn status = new DataGridViewImageColumn(); status.DisplayIndex = ; ...

  7. WinForm - 格式化DataGridView单元格数据

    效果: 代码: /// <summary> /// 格式化数据 /// </summary> private void dataGridView1_CellFormatting ...

  8. Winform Datagridview 单元格html格式化支持富文本

    Winform Datagridview 单元格html格式化支持富文本 示例: 源码:https://github.com/OceanAirdrop/DataGridViewHTMLCell 参考: ...

  9. WinForm笔记1:TextBox编辑时和DataGridView 单元格编辑时 的事件及其顺序

    TextBox 编辑框 When you change the focus by using the mouse or by calling the Focus method, focus event ...

随机推荐

  1. 初学SpringBoot遇到的坑和笔记

    目录 1.日期返回给前端显示不理想问题 1.1重现 1.2原因 1.3解决 1.4结果 2.MyBatis-Plus数据库字段未找到问题 2.1重现 2.2原因 2.3解决 3.Long型雪花主键返回 ...

  2. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

    MFC中ASSERT作为断言语句,括号内内容为TRUE,继续执行:为FALSE终止执行.之后取得当前窗口的系统菜单,在这个菜单中添加字符串资源IDS_ABOUTBOX和菜单资源IDM_ABOUTBOX ...

  3. python — 进程

    目录 1. 进程 1.进程就是一个运行中的程序(是对正在运行程序的一个抽象). 2.程序和进程之间的区别: 程序只是一个文件 进程是这个文件被CPU运行起来了 程序是永久的,进程是暂时的. 3.进程- ...

  4. iView组件Tabs嵌套使用

    <Tabs name="tab" value="a"> <TabPane label="标签a" name="a ...

  5. 执行jar包,输出信息到文件

    有时如果临时需要上项目执行一些脚本或者临时文件,可以将项目达成jar包,去执行 执行jar包: java -jar test.jar 输出日志到文件:nohup java -jar test.jar ...

  6. Hinton等人最新研究:大幅提升模型准确率,标签平滑技术到底怎么用?

    Hinton等人最新研究:大幅提升模型准确率,标签平滑技术到底怎么用? 2019年07月06日 19:30:55 AI科技大本营 阅读数 675   版权声明:本文为博主原创文章,遵循CC 4.0 B ...

  7. 24-Perl 数据库连接

    1.Perl 数据库连接本章节我们将为大家介绍 Perl 数据库的连接.Perl 5 中我们可以使用 DBI 模块来连接数据库.DBI 英文全称:Database Independent Interf ...

  8. 三、maven学习-高级

    maven父子工程

  9. 【Git的基本操作四】永久删除文件后找回

    永久删除文件后找回 1. 已经添加到本地库的文件 使用 reset 命令回退到未删除的历史记录即可 2.添加到缓存区,没有提交到本地库的文件找回 git reset --hard HEAD 命令即可找 ...

  10. idea tomcat 乱码问题的解决及相关设置

    问题,在idea中出现乱码问题,以前没有的,好像在设置系统代码为utf8之后就出现了,于是尝试了一系列办法,希望这些办法对您有帮助. 先看一下乱码的样式. 设置办法 1.在tomcat Server中 ...