自定义控件:DataGridView多维表头

[datagridview与treeview绑定]

treeview

          

代码:

            DataTable dtable = new DataTable("Rock");
            //添加8列
            dtable.Columns.Add("1", typeof(System.String));
            dtable.Columns.Add("2", typeof(System.String));
            dtable.Columns.Add("3", typeof(System.String));
            dtable.Columns.Add("4", typeof(System.String));
            dtable.Columns.Add("5", typeof(System.String));
            dtable.Columns.Add("6", typeof(System.String));
            dtable.Columns.Add("7", typeof(System.String));
            dtable.Columns.Add("8", typeof(System.String));
            //添加一行数据
            DataRow drow = dtable.NewRow();
            drow["1"] = "11";
            drow["2"] = "22";
            drow["3"] = "33";
            drow["4"] = "44";
            drow["5"] = "55";
            drow["6"] = "66";
            drow["7"] = "77";
            drow["8"] = "88";
            dtable.Rows.Add(drow);
            //绑定数据
            multiColHeaderDgv2.DataSource = dtable;

datagridview多维表头实现效果:

自定义控件全部代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

namespace myMultiColHeaderDgv
{
    public  class MultiColHeaderDgv:DataGridView
    {        

        #region 字段定義

        /// <summary>多維列標題的樹結構
        ///
        /// </summary>
        private TreeView _ColHeaderTreeView;

        /// <summary>樹的最大層數
        ///
        /// </summary>
        private int iNodeLevels;

        /// <summary>一維列標題的高度
        ///
        /// </summary>
        private int iCellHeight;

        /// <summary>所有葉節點
        ///
        /// </summary>
        private IList<TreeNode> ColLists = new List<TreeNode>();

         #endregion

        #region 屬性定義

        /// <summary>多維列標題的樹結構
        ///
        /// </summary>
        [
          Description("多維列標題的樹結構")
        ]
        public TreeView myColHeaderTreeView
        {
            get { return _ColHeaderTreeView; }
            set { _ColHeaderTreeView = value; }
        }

        #endregion

        #region 方法函數

        /// <summary>遞歸計算樹最大層數,並保存所有葉節點
        ///
        /// </summary>
        /// <param name="tnc"></param>
        /// <returns></returns>
        private int myGetNodeLevels(TreeNodeCollection tnc)
        {
            if (tnc == null) return 0;

            foreach (TreeNode tn in tnc)
            {
                if ((tn.Level + 1) > iNodeLevels)//tn.Level是從0開始的
                {
                    iNodeLevels = tn.Level+1;
                }

                if (tn.Nodes.Count > 0)
                {
                    myGetNodeLevels(tn.Nodes);
                }
                else
                {
                    ColLists.Add(tn);//葉節點
                }
            }

            return iNodeLevels;
        }

        /// <summary>調用遞歸求最大層數、列頭總高
        ///
        /// </summary>
        public void myNodeLevels()
        {

            iNodeLevels = 1;//初始為1

            ColLists.Clear();

            int iNodeDeep = myGetNodeLevels(_ColHeaderTreeView.Nodes);

            iCellHeight = this.ColumnHeadersHeight;

            this.ColumnHeadersHeight = this.ColumnHeadersHeight * iNodeDeep;//列頭總高=一維列高*層數

        }

        /// <summary>获得合并标题字段的宽度
        ///
        /// </summary>
        /// <param name="node">字段节点</param>
        /// <returns>字段宽度</returns>
        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 <= ColLists.Count - 1; i++)
            {
                if (ColLists[i].Equals(node))
                    return i;
            }
            return -1;
        }

        ///<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 * iCellHeight,
                            uhWidth - 1,
                            iCellHeight * (iNodeLevels  - node.Level) - 1);
            }
            else
            {
                uhRectangle = new Rectangle(
                            e.CellBounds.Left,
                            e.CellBounds.Top + node.Level * iCellHeight,
                            uhWidth - 1,
                            iCellHeight - 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);

            e.Graphics.DrawString(node.Text, this.ColumnHeadersDefaultCellStyle.Font
                                    , Brushes.Black
                                    , uhRectangle.Left + uhRectangle.Width / 2 -
                                    e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Width / 2 - 1
                                    , uhRectangle.Top +
                                    uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Height / 2);

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

        #endregion

        //重寫表頭
        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            try
            {
                //行标题不重写
                if (e.ColumnIndex < 0)
                {
                    base.OnCellPainting(e);
                    return;
                }

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

                //绘制表头
                if (e.RowIndex == -1)
                {
                    if (_ColHeaderTreeView != null)
                    {
                        if (iNodeLevels == 0)
                        {
                            myNodeLevels();
                        }

                        PaintUnitHeader((TreeNode)this.ColLists[e.ColumnIndex], e, iNodeLevels);

                        e.Handled = true;
                    }
                    else
                    {
                        base.OnCellPainting(e);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error");
            }
        }
    }
}

using System;using System.Collections.Generic;using System.Text;using System.Windows.Forms;using System.Drawing;using System.ComponentModel;
namespace myMultiColHeaderDgv{    public  class MultiColHeaderDgv:DataGridView    {        
        #region 字段定義
        /// <summary>多維列標題的樹結構        ///         /// </summary>        private TreeView _ColHeaderTreeView;                   /// <summary>樹的最大層數        ///         /// </summary>        private int iNodeLevels;
        /// <summary>一維列標題的高度        ///         /// </summary>        private int iCellHeight;
        /// <summary>所有葉節點        ///         /// </summary>        private IList<TreeNode> ColLists = new List<TreeNode>();
         #endregion
        #region 屬性定義
        /// <summary>多維列標題的樹結構        ///         /// </summary>        [          Description("多維列標題的樹結構")        ]        public TreeView myColHeaderTreeView        {            get { return _ColHeaderTreeView; }            set { _ColHeaderTreeView = value; }        }
        #endregion
        #region 方法函數
        /// <summary>遞歸計算樹最大層數,並保存所有葉節點        ///         /// </summary>        /// <param name="tnc"></param>        /// <returns></returns>        private int myGetNodeLevels(TreeNodeCollection tnc)        {            if (tnc == null) return 0;
            foreach (TreeNode tn in tnc)            {                if ((tn.Level + 1) > iNodeLevels)//tn.Level是從0開始的                {                    iNodeLevels = tn.Level+1;                }
                if (tn.Nodes.Count > 0)                {                                        myGetNodeLevels(tn.Nodes);                }                else                {                    ColLists.Add(tn);//葉節點                }            }
            return iNodeLevels;        }
        /// <summary>調用遞歸求最大層數、列頭總高        ///         /// </summary>        public void myNodeLevels()        {
            iNodeLevels = 1;//初始為1
            ColLists.Clear();
            int iNodeDeep = myGetNodeLevels(_ColHeaderTreeView.Nodes);
            iCellHeight = this.ColumnHeadersHeight;
            this.ColumnHeadersHeight = this.ColumnHeadersHeight * iNodeDeep;//列頭總高=一維列高*層數
        }
        /// <summary>获得合并标题字段的宽度        ///         /// </summary>        /// <param name="node">字段节点</param>        /// <returns>字段宽度</returns>        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 <= ColLists.Count - 1; i++)            {                if (ColLists[i].Equals(node))                    return i;            }            return -1;        }
        ///<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 * iCellHeight,                            uhWidth - 1,                            iCellHeight * (iNodeLevels  - node.Level) - 1);            }            else            {                uhRectangle = new Rectangle(                            e.CellBounds.Left,                            e.CellBounds.Top + node.Level * iCellHeight,                            uhWidth - 1,                            iCellHeight - 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);
            e.Graphics.DrawString(node.Text, this.ColumnHeadersDefaultCellStyle.Font                                    , Brushes.Black                                     , uhRectangle.Left + uhRectangle.Width / 2 -                                    e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Width / 2 - 1                                    , uhRectangle.Top +                                    uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Height / 2);
            //递归调用()            if (node.PrevNode == null)                if (node.Parent != null)                    PaintUnitHeader(node.Parent, e, level - 1);        }
        #endregion
        //重寫表頭        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)        {            try            {                //行标题不重写                if (e.ColumnIndex < 0)                {                    base.OnCellPainting(e);                    return;                }
                if (iNodeLevels == 1)                {                    base.OnCellPainting(e);                    return;                }
                //绘制表头                if (e.RowIndex == -1)                {                    if (_ColHeaderTreeView != null)                    {                        if (iNodeLevels == 0)                        {                            myNodeLevels();                        }
                        PaintUnitHeader((TreeNode)this.ColLists[e.ColumnIndex], e, iNodeLevels);
                        e.Handled = true;                    }                    else                    {                        base.OnCellPainting(e);                    }                }            }            catch (Exception ex)            {                MessageBox.Show(this, ex.Message, "Error");            }        }    }}

时间: 03-07

自定义控件:DataGridView多维表头的相关文章

GJM:C# WinForm开发系列 - DataGridView 使用方法集锦 [转载]

1.DataGridView实现课程表 testcontrol.rar 2.DataGridView二维表头及单元格合并 DataGridView单元格合并和二维表头.rar myMultiColHeaderDgv.rar 3.DataGridView单元格显示GIF图片 gifanimationindatagrid.rar 4.自定义显示DataGridView列(行头显示行号与图标,同一单元格显示图片也显示文字)TestDataGridViewRowStyle2.rar 5.扩展DataGr

在流布局里面动态添加自定义控件,通过简单的按钮分页技术

由于最近没什么事情,一直在看java基础,前几天接到上级的任务,得作出一个门禁系统的cs界面出来,能够实现分页,数据绑定需求如下图 看到这里,因为我基本没接触过cs的东西,一时间只有两三个思路,第一个思路是:自定义控件+panle控件(最终感觉行不通没有去做) 第二个思路是:自定义控件+DataGridView控件,尝试了几天,感觉方法有点繁琐,而且不一定能实现这种效果: 第三个思路是:自定义控件+流布局+自动生成.最终我通过第三种方法做出来了: 第四个思路是:wcf 只是有这个思路,还没有去实

DataGridView 表头中添加过滤列表(类似Excel表头过滤)

Building a Drop-Down Filter List for a DataGridView Column Header Cell 参考:http://msdn.microsoft.com/zh-cn/library/aa480727(en-us).aspx 1.引用DataGridViewAutoFilter.dll文件 2.C#程序调用时,只需要添加: BindingSource dataSource = new BindingSource(_DataView, null);dat

.NET WinForm程序中给DataGridView表头添加下拉列表实现数据过滤

转:http://www.cnblogs.com/jaxu/archive/2011/08/04/2127365.html 我们见过Excel中的数据过滤功能,可以通过点击表头上的下拉列表来实现数据的过滤,这个功能很实用,省去了我们需要在程序中单独设计数据的查询过滤模块,功能直接依赖于数据绑定控件DataGridView.先来看看Excel中的数据过滤功能. 要想在DataGridView中实现类似于Excel的这种功能其实也并非难事.来看看msdn上的一篇文章,上面有详细的介绍,不过目前只有全

EasyUI-Datagrid二维表格:多表头

人力资源管理有个做二维表格的需求,客户的需求是这样的,如图: 由于是从零开始,没有参考,我就想用easyui 做一下.分析需求,其实难点就三个:1.是将上表头的部分单元格合并.2.是在左侧显示标题.3.是页内单元格可以编辑. 对于easyui来说,单元格合并比较简单,写table时的核心的代码就两句:rowspan 和colspan.其中,rowspan是合并上下,colspan是合并左右. <span style="font-family:Verdana;font-size:18px;&

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

机房收费(2)——DataGridView控件使用

机房收费系统很多功能都涉及到数据在表中的显示,在VB 6.0敲第一次机房的时候,我们应用到控件MSHFlexGrid,而 .NET应用的是DataGridView,感觉DataGridView强大多了,而且也很方便,可以直接和数据库绑定,实现对数据库的操作:也可以使用代码对DataGridView进行操作,实现相应的功能. DataGridView控件优点众多,它不仅可以灵活的显示数据,而且能够轻松的根据需要定义控件外观,通过一行代码就可以实现数据的绑定,完全可视化操作,方便快捷了不少. 接下来

.Net中DataGridview数据如何导出到excel表

首先,这个问题在网上有很多答案,也有很多解决的方法.其次,很多人写过类似的博客 .我的这篇博客,主要是写给那些刚刚接触或接触不久.NET并使用其做程序的人,更是写个自己,记录一下方法,方便以后使用. 在窗体中添加一个DataGridView控件,DatagridView获得数据: DataGridView1.DataSource = crList(泛型)或DataGridView1.DataSource=DataSet.Table(0).{注意:通过查询数据库,将查询到的数据放入crList或D

C# 自定义重绘DataGridView

using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; using System.Runtime.CompilerServices; using System.Drawing.Drawing2D; na