DataGridView的复合表头

e0d9dabf21fea01c18d81f72.jpg

本实现方法为网上流传最广的方法,本人做了一些修改,修正一些可能出现的BUG.

下面是自定义控件源码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Sql;
using System.Text;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace MultiHeaderDataGridView
{
public partial class HeaderUnitView : DataGridView
{
private TreeView[] _columnTreeView;
private ArrayList _columnList = new ArrayList();
private int _cellHeight = 17;

        public int CellHeight
{
get { return _cellHeight; }
set { _cellHeight = value; }
}
private int _columnDeep = 1;

        /// <summary>
/// 构造函数
/// </summary>
public HeaderUnitView()
{
InitializeComponent();
this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
//设置列高度显示模式           
}

        [Description("设置或获得合并表头树的深度")]
public int ColumnDeep
{
get
{
if (this.Columns.Count == 0)
_columnDeep = 1;

                this.ColumnHeadersHeight = _cellHeight * _columnDeep;
return _columnDeep;
}

            set
{
if (value < 1)
_columnDeep = 1;
else
_columnDeep = value;
this.ColumnHeadersHeight = _cellHeight * _columnDeep;
}
}


[Description("添加合并式单元格绘制的所需要的节点对象")]
public TreeView[] ColumnTreeView
{
get { return _columnTreeView; }
set
{
if (_columnTreeView != null)
{
for (int i = 0; i <= _columnTreeView.Length - 1; i++)
_columnTreeView[i].Dispose();
}
_columnTreeView = value;
}
}

        [Description("设置添加的字段树的相关属性")]
public TreeView ColumnTreeViewNode
{
get { return _columnTreeView[0]; }
}

        public ArrayList NadirColumnList
{
get
{
if (_columnTreeView == null)
return null;

                if (_columnTreeView[0] == null)
return null;

                if (_columnTreeView[0].Nodes == null)
return null;

                if (_columnTreeView[0].Nodes.Count == 0)
return null;

                _columnList.Clear();
GetNadirColumnNodes(_columnList, _columnTreeView[0].Nodes[0], false);
return _columnList;
}
}


///<summary>
///绘制合并表头
///</summary>
///<param name="node">合并表头节点</param>
///<param name="e">绘图参数集</param>
///<param name="level">结点深度</param>
///<remarks></remarks>
public void PaintUnitHeader(
TreeNode node,
System.Windows.Forms.DataGridViewCellPaintingEventArgs e,
int level)
{
//根节点时退出递归调用
if (level == 0)
return;

RectangleF uhRectangle;
int uhWidth;
SolidBrush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backColorBrush = new SolidBrush(e.CellStyle.BackColor);
Pen gridLinePen = new Pen(gridBrush);
StringFormat textFormat = new StringFormat();


textFormat.Alignment = StringAlignment.Center;

            uhWidth = GetUnitHeaderWidth(node);

            if( node.Nodes.Count == 0)
{
uhRectangle = new Rectangle(e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight * (_columnDeep - node.Level) - 1);
}
else
{  
uhRectangle = new Rectangle(
e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight - 1);
}

            //画矩形
e.Graphics.FillRectangle(backColorBrush, uhRectangle);

//划底线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Left
, uhRectangle.Bottom
, uhRectangle.Right
, uhRectangle.Bottom);
//划右端线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Right
, uhRectangle.Top
, uhRectangle.Right
, uhRectangle.Bottom);
写字段文本
Brush brush=new SolidBrush(e.CellStyle.ForeColor);           

e.Graphics.DrawString(node.Text, this.Font
, new SolidBrush(e.CellStyle.ForeColor)
, uhRectangle.Left +uhRectangle.Width / 2-
e.Graphics.MeasureString(node.Text, this.Font).Width / 2 - 1
, uhRectangle.Top +
uhRectangle.Height / 2 -e.Graphics.MeasureString(node.Text, this.Font).Height / 2);

            递归调用()
if (node.PrevNode == null)
if (node.Parent != null)
PaintUnitHeader(node.Parent, e, level - 1);
}      

        /// <summary>
/// 获得合并标题字段的宽度
/// </summary>
/// <param name="node">字段节点</param>
/// <returns>字段宽度</returns>
/// <remarks></remarks>
private int GetUnitHeaderWidth(TreeNode node)
{
//获得非最底层字段的宽度

            int uhWidth = 0;
//获得最底层字段的宽度
if (node.Nodes == null)
return this.Columns[GetColumnListNodeIndex(node)].Width;

            if (node.Nodes.Count == 0)
return this.Columns[GetColumnListNodeIndex(node)].Width;

            for (int i = 0; i <= node.Nodes.Count - 1; i++)
{
uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes[i]);
}
return uhWidth;
}


/// <summary>
/// 获得底层字段索引
/// </summary>
///' <param name="node">底层字段节点</param>
/// <returns>索引</returns>
/// <remarks></remarks>
private int GetColumnListNodeIndex(TreeNode node)
{
for (int i = 0; i <= _columnList.Count - 1; i++)
{
if (((TreeNode)_columnList[i]).Equals(node))
return i;
}
return -1;
}


/// <summary>
/// 获得底层字段集合
/// </summary>
/// <param name="alList">底层字段集合</param>
/// <param name="node">字段节点</param>
/// <param name="checked">向上搜索与否</param>
/// <remarks></remarks>
private void GetNadirColumnNodes(
ArrayList alList,
TreeNode node,
Boolean isChecked)
{
if (isChecked == false)
{
if (node.FirstNode == null)
{
alList.Add(node);
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
}
if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
else
{
if (node.FirstNode != null)
{
GetNadirColumnNodes(alList, node.FirstNode, false);
return;
}
}
}
else
{
if (node.FirstNode == null)
{
return;
}
else
{
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
}

                    if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
}
}
/// <summary>
/// 滚动
/// </summary>
/// <param name="e"></param>
protected override void OnScroll(ScrollEventArgs e)
{
base.OnScroll(e);
//this.Refresh();
}
/// <summary>
/// 列宽度改变的重写
/// </summary>
/// <param name="e"></param>
protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
{
Graphics g = Graphics.FromHwnd(this.Handle);
float uwh = g.MeasureString(e.Column.HeaderText, this.Font).Width;
if (uwh >= e.Column.Width) {
e.Column.Width = Convert.ToInt16(uwh) + 1;               
}
base.OnColumnWidthChanged(e);
//this.Refresh();
}

/// <summary>
/// 单元格绘制(重写)
/// </summary>
/// <param name="e"></param>
/// <remarks></remarks>
protected override void OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
{
try
{
//行标题不重写
if (e.ColumnIndex < 0)
{
base.OnCellPainting(e);
return;
}

                if (_columnDeep == 1)
{
base.OnCellPainting(e);
return;
}

                //绘制表头
if (e.RowIndex == -1)
{
if (e.ColumnIndex >= NadirColumnList.Count) { e.Handled = true; return; }                   
Application.DoEvents();
PaintUnitHeader((TreeNode)NadirColumnList[e.ColumnIndex]
, e
, _columnDeep);
e.Handled = true;
}
}
catch
{ }
}        
}
}

生成些控件方法:

private MultiHeaderDataGridView.HeaderUnitView createDataGridView()

{

MultiHeaderDataGridView.HeaderUnitView dgv=new MultiHeaderDataGridView.HeaderUnitView();

TreeView treeview = new TreeView();//生成一个树

TreeNode tn = new TreeNode();

tn.Text = "node1"; treeview.Nodes.Add(tn); tn = new TreeNode(); tn.Text = "node2"; treeview.Nodes[0].Nodes.Add(tn);

tn = new TreeNode(); tn.Text = "node3"; treeview.Nodes[0].Nodes.Add(tn);

dgv.Columns.Add("column1");//添加列   

dgv.Columns.Add("column2");//添加列   

dgv.ColumnTreeView = new TreeView[] { treeview };
dgv.ColumnDeep = 2;//列深
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dgv.AutoGenerateColumns = false;                                    //不自动增加列
dgv.RowHeadersVisible = false;                                      //行头不可见

}

这样就可以生成一个一个大列下有二个小列的表.......复杂的表头同样的源理.

如果有三层表头就把ColumnDeep改成3,,依次...

转载于:https://www.cnblogs.com/605395451/archive/2011/08/25/2153842.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、对于MyMulDataGridViewHeader的使用的一个简单的示例 1、数据表 use master go --创建数据库 if exists(select * from sys.sysdatabases where name='TestDB') drop database TestDB go create database TestDB on ( name ='TestDB_data', filename = 'E:\Data\TestDB_data.mdf', size = 5mb, maxsize = 20mb, filegrowth = 10% ) log on ( name ='TestDB_log', filename = 'E:\Data\TestDB_log.ldf', size =3mb, maxsize = 10mb, filegrowth = 1mb ) go use TestDB go if exists(select * from sys.tables where name='UserInfo') drop table UserInfo go create table UserInfo ( id int primary key identity(1,1), uname varchar(20) not null, usex int not null, uage int not null, chineseremark int not null, matchremark int not null, englishremark int not null ) go insert into userinfo values('小谭',1,21,82,90,81) insert into userinfo values('小花',0,21,83,90,82) insert into userinfo values('小华',0,20,84,90,99) insert into userinfo values('小方',0,20,85,92,85) insert into userinfo values('小高',0,21,86,90,88) insert into userinfo values('小宁',1,21,87,90,89) insert into userinfo values('小江',1,21,88,90,92) insert into userinfo values('小艳',0,20,89,90,93) insert into userinfo values('小琼',0,21,92,98,95) go select * from userinfo //后台调用 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using MyDataGridMultiHeaderHelp; namespace MyTest { public partial class Form3 : Form { public Form3() { InitializeComponent(); } DataGridView dgv = new DataGridView(); private void Form3_Load(object sender, EventArgs e) { SqlConnection conn = new SqlConnection("Server=.;DataBase=TestDB;Uid=sa;Pwd=123456"); SqlCommand cmd = new SqlCommand("select * from userinfo", conn); SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = cmd; DataSet ds = new DataSet(); sda.Fill(ds); DataTable dt = ds.Tables[0]; //清除原有的控件 if (dgv != null && dgv.Name != "Mydgv") { panel1.Controls.RemoveByKey(dgv.Name); dgv.Dispose(); dgv = null; } dgv = CreateDataGridView(); dgv.DataSource = dt; this.panel1.Controls.Add(dgv); } private MyMulDataGridViewHeader CreateDataGridView() { MyMulDataGridViewHeader dgv = DataIntance.InstanceDataGridView(); DataIntance intance = new DataIntance(dgv); TreeView mytv = new TreeView();//实例树。以树节点为多表头节点 intance.SetData(mytv.Nodes, "学员信息表"); intance.SetData(mytv.Nodes[0].Nodes, "ID编号"); intance.SetData(mytv.Nodes[0].Nodes, "姓名"); intance.SetData(mytv.Nodes[0].Nodes, "性别"); intance.SetData(mytv.Nodes[0].Nodes, "年龄"); intance.SetData(mytv.Nodes[0].Nodes, "成绩"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "语文"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "数学"); intance.SetData(mytv.Nodes[0].Nodes[4].Nodes, "英语"); intance.SetProperty("ID"); intance.SetProperty("uname"); intance.SetProperty("usex"); intance.SetProperty("uage"); intance.SetProperty("chineseremark"); intance.SetProperty("matchremark"); intance.SetProperty("englishremark"); dgv.ColumnTreeView = new TreeView[] { mytv }; dgv.ColumnDeep = 3; return dgv; } } } 二、GridView多表头的使用 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.SqlClient; using System.Data; using MyDataGridMultiHeaderHelp; namespace MyWeb { public partial class GridViewMulRow : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { GetMulData(); } } private void GetMulData() { SqlConnection conn = new SqlConnection("Server=.;DataBase=TestDB;Uid=sa;Pwd=123456"); SqlCommand cmd = new SqlCommand("select * from userinfo", conn); SqlDataAdapter sda = new SqlDataAdapter(); sda.SelectCommand = cmd; DataSet ds = new DataSet(); sda.Fill(ds); DataTable dt = ds.Tables[0]; this.gvTest.DataSource = dt; this.gvTest.DataBind(); TableCellCollection tcHeader = this.gvTest.HeaderRow.Cells; tcHeader.Clear(); GridViewMulRowHeader gv = new GridViewMulRowHeader(tcHeader); gv.InstanceTableCell("学员信息表</th></tr><tr>", "colspan", "7"); gv.InstanceTableCell("ID编号", "rowspan", "2"); gv.InstanceTableCell("姓名", "rowspan", "2"); gv.InstanceTableCell("性别", "rowspan", "2"); gv.InstanceTableCell("年龄", "rowspan", "2"); gv.InstanceTableCell("成绩</th></tr><tr>", "colspan", "3"); gv.InstanceTableCell("语文"); gv.InstanceTableCell("数学"); gv.InstanceTableCell("英语"); } } }
### 回答1: datagridview表头是用来显示列名的,默认情况下是可以看到的。如果你需要禁止表头的显示,可以通过以下步骤实现: 1. 打开窗体的设计视图,在DataGridView控件的属性窗口中找到Columns属性。 2. 单击Columns属性旁边的“…”按钮,打开列编辑器。 3. 在编辑器中,为每一列设置HeaderText属性为相应的列名,这样在表头处就会显示列名。 4. 在DataGridView的属性窗口中,找到ColumnHeadersVisible属性,将其值设置为False,这样表头就被隐藏起来了。 这样做之后,你将看到在运行时表头不再显示,只有数据行可见。请注意,这只是隐藏了表头的显示,并不会删除或者改变表头的结构,因此你仍然可以通过代码或者其他方式来操作和访问表头。 ### 回答2: 要禁止 DataGridView表头,可以使用以下方法: 1. 设置 DataGridView 的 ColumnHeadersVisible 属性为 False。这将隐藏整个表头,并且禁用了对表头的排序、拖动列等操作。代码示例: DataGridView1.ColumnHeadersVisible = False 2. 如果你只想禁止用户拖动列而保留表头的显示和其他操作,可以使用 ColumnHeadersHeightSizeMode 属性来禁用拖动功能。代码示例: DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing 3. 如果你希望保留表头的显示,但要禁用所有的表头操作,可以使用 HeaderCell 属性来禁用鼠标事件并移除掉所有的 ContextMenuStrip。代码示例: For Each col As DataGridViewColumn In DataGridView1.Columns col.HeaderCell = New DataGridViewColumnHeaderCell() With { .Value = col.HeaderText, .ToolTipText = col.HeaderText, .ContextMenuStrip = Nothing } Next 无论使用哪种方法,都可以有效地禁止 DataGridView表头操作。根据具体的需求,选择适合的方法即可。 ### 回答3: DataGridView是.NET Framework中的一个控件,用于展示和编辑数据。如果要禁用DataGridView表头,可以使用以下方法: 1. 设置DataGridView的ColumnHeadersVisible属性为False。这将隐藏掉整个表头部分,包括列名和排序按钮。 2. 使用样式设置隐藏表头。首先,可以通过设置DataGridView的EnableHeadersVisualStyles属性为False,禁用默认的表头样式。然后,可以通过修改DataGridView的DefaultCellStyle属性来隐藏表头的外观,比如将表头的字体颜色设置为与背景颜色相同。 3. 使用尺寸调整行隐藏表头。在DataGridView的RowHeadersVisible属性为False的情况下,可以通过将表头行的高度设置为0,来隐藏掉表头。这样表头行将不可见,但是单元格内容仍然可以正常显示和编辑。 总结起来,禁止DataGridView表头可以通过隐藏整个表头、修改样式或调整行高度等方式来实现。具体选择哪种方式取决于实际需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值