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. Nginx整合Tomcat

    现在先不考虑集群的配置问题,只实现Nginx实现一台tomact的代理 1.我们需要一个web项目,这里我把先准备好的web.war文件部署到Tomact服务器上 mvn clean install ...

  2. vue中关于checkbox数据绑定v-model指令说明

    vue.js为开发者提供了很多便利的指令,其中v-model用于表单的数据绑定很常见, 下面是最常见的例子: <div id='myApp'> <input type="c ...

  3. 函数try{}

    语法 函数try块是一种函数体的替代语法形式,是函数定义的一部分 try构造函数初始化器 复合语句 处理块序列 (1)构造函数初始化器 - 成员初始化器列表,只在构造函数允许 (2)复合语句 - 花括 ...

  4. Treasure Island(两遍dfs)-- Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises)

    题意:https://codeforc.es/contest/1214/problem/D 给你一个n*m的图,每次可以往右或者往下走,问你使(1,1)不能到(n,m)最少要放多少 ‘ # ’ . 思 ...

  5. union和in哪个效率高

    一直都认为是in的效率要高,但是这次确有点蒙圈. SELECT * FROM runinfo WHERE status in (0,2,1,3,4,7,9,10); 这个查询的效率是,经常是1秒多. ...

  6. C - 简易贪吃蛇的编写

    不多废话,直接进入正题——用C编写简易贪吃蛇.附上拙劣的源码 * c-snake * 首先说明使画面动起来的原理:通过 system("cls"); 清除当前控制台的显示,再pri ...

  7. ubuntu 系统升级

    1.更新软件源和软件 $ sudo apt-get update && sudo apt-get dist-upgrade 2.安装update-manager-core $ sudo ...

  8. C#开发微信公众平台-就这么简单(转载)(附原文链接)

    一直使用的是一百八的诺鸡鸭,没有想去接触看起来风风火火的移动互联网:但因工作需要维护一个微信公众订阅号,考虑以前有做网站的基础,就想着做个简单的微信后台管理:看了官方的开发文档,比狗哥地图的短许多,又 ...

  9. C# 操作地址 从内存中读取写入数据(初级)

    本示例以植物大战僵尸为例, 实现功能为 每1秒让阳光刷新为 9999.本示例使用的游戏版本为 [植物大战僵尸2010年度版], 使用的辅助查看内存地址的工具是  CE. 由于每次启动游戏, 游戏中阳光 ...

  10. yolov3应该什么时候停止训练?

    按照训练期间的参数提示: Region Avg IOU:0.798363,Class:0.893232,Obj:0.700808,No Obj:0.004567,Avg Recall:1.000000 ...