[datagridview与treeview绑定]

treeview

          

代码:

            DataTable dtable = new DataTable("Rock");
//添加8列
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
dtable.Columns.Add("", typeof(System.String));
//添加一行数据
DataRow drow = dtable.NewRow();
drow[""] = "";
drow[""] = "";
drow[""] = "";
drow[""] = "";
drow[""] = "";
drow[""] = "";
drow[""] = "";
drow[""] = "";
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 ; foreach (TreeNode tn in tnc)
{
if ((tn.Level + ) > iNodeLevels)//tn.Level是從0開始的
{
iNodeLevels = tn.Level+;
} if (tn.Nodes.Count > )
{
myGetNodeLevels(tn.Nodes);
}
else
{
ColLists.Add(tn);//葉節點
}
} return iNodeLevels;
} /// <summary>調用遞歸求最大層數、列頭總高
///
/// </summary>
public void myNodeLevels()
{ iNodeLevels = ;//初始為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 = ;
//获得最底层字段的宽度
if (node.Nodes == null)
return this.Columns[GetColumnListNodeIndex(node)].Width; if (node.Nodes.Count == )
return this.Columns[GetColumnListNodeIndex(node)].Width; //获得非最底层字段的宽度
for (int i = ; i <= node.Nodes.Count - ; 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 = ; i <= ColLists.Count - ; i++)
{
if (ColLists[i].Equals(node))
return i;
}
return -;
} ///<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 == )
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 == )
{
uhRectangle = new Rectangle(e.CellBounds.Left,
e.CellBounds.Top + node.Level * iCellHeight,
uhWidth - ,
iCellHeight * (iNodeLevels - node.Level) - );
}
else
{
uhRectangle = new Rectangle(
e.CellBounds.Left,
e.CellBounds.Top + node.Level * iCellHeight,
uhWidth - ,
iCellHeight - );
} //画矩形
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 / -
e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Width / -
, uhRectangle.Top +
uhRectangle.Height / - e.Graphics.MeasureString(node.Text, this.ColumnHeadersDefaultCellStyle.Font).Height / ); //递归调用()
if (node.PrevNode == null)
if (node.Parent != null)
PaintUnitHeader(node.Parent, e, level - );
} #endregion //重寫表頭
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
try
{
//行标题不重写
if (e.ColumnIndex < )
{
base.OnCellPainting(e);
return;
} if (iNodeLevels == )
{
base.OnCellPainting(e);
return;
} //绘制表头
if (e.RowIndex == -)
{
if (_ColHeaderTreeView != null)
{
if (iNodeLevels == )
{
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");            }        }    }}

【Winform-自定义控件】 DataGridView多维表头的更多相关文章

  1. (转)DataGridView多维表头及其扩展功能

    dataGridView1.RowHeadersVisible = false;把整行选中那一列去掉.如果需要整行选中,新增一按钮列模拟实现.上源码:多维DataGridView 有个简易的方法: 1 ...

  2. C#中Winform程序中如何实现多维表头【不通过第三方报表程序】

    问题:C#中Winform程序中如何实现多维表头. 在网上搜了很多方法,大多数方法对于我这种新手,看的都不是很懂.最后在新浪博客看到了一篇比较易懂的文章:[DataGridView二维表头与合并单元格 ...

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

    DataGridView单元格合并和二维表头应用: //DataGridView绑定数据 DataTable dt = new DataTable(); dt.Columns.Add("); ...

  4. Datagridview 实现二维表头和行合并【转载】

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; u ...

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

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

  6. (八十九)c#Winform自定义控件-自定义滚动条(treeview、panel、datagridview、listbox、listview、textbox)

    官网 http://www.hzhcontrols.com/ 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kw ...

  7. C#winform自定义控件大全

    对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. 基础 - 常用控件 C# WinForm开发系列 - CheckBox/Button/Lab ...

  8. 关于Winform下DataGridView中实现checkbox全选反选、同步列表项的处理

    近期接手一个winform 项目,虽然之前有.net 的经验,但是对一些控件的用法还不是很熟悉. 这段时间将会记录一些在工作中遇到的坎坷以及对应的解决办法,写出来与大家分享并希望大神提出更好解决方法来 ...

  9. (三十二)c#Winform自定义控件-表格

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

随机推荐

  1. LC 155 Min Stack

    问题描述 Design a stack that supports push, pop, top, and retrieving the minimum element in constant tim ...

  2. LC 752 Open the Lock

    由于这个问题,涉及了很多知识,例如数据结构里面的哈希表,c++中的迭代器,因此,需要对于每一个疑惑逐一击破. 问题描述 You have a lock in front of you with 4 c ...

  3. python 基础(十九)--re正则表达式模块

    正则表达式模式 模式 描述 ^ 匹配字符串的开头 $ 匹配字符串的末尾. . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符. [...] 用来表示一组字符 ...

  4. Java中的float、double计算精度问题

    java中的float.double计算存在精度问题,这不仅仅在java会出现,在其他语言中也会存在,其原因是出在IEEE 754标准上. 而java对此提供了一个用于浮点型计算的类——BigDeci ...

  5. -bash: fork: retry: 没有子进程

    今天遇到一个问题 -bash: fork: retry: 没有子进程 解决方法 设置各linux 用户的最大进程数,下面我把某linux用户的最大进程数设为10000个:   ulimit -u 10 ...

  6. asp.net 10 Cookie & Session

    Cookie 1.什么是Cookie 一小段文本,明文的数据,关于网站相关的文本字符串数据.一个客户端状态保持机制~ 存储在客户端的浏览器内存里面或者磁盘(如果不指定过期时间,那么存储在客户端浏览器内 ...

  7. QT 安卓 悬浮窗权限动态申请

    一:申请方式: String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMI ...

  8. ZROI2018暑期集训B班训练赛#1解题报告

    版权原因不公布题目信息 A 分析 虽然前一天搞到比较晚,考场上还是比较快的想到了正解,可惜姿势水平低被卡到了64(进入高中不知道考过多少次64了...) 这题有个比较明显且\(naive\)的做法是用 ...

  9. 支付宝小程序室内地图导航开发-支付宝小程序JS加载esmap地图

    如果是微信小程序开发,请参考微信小程序室内地图导航开发-微信小程序JS加载esmap地图文章 一.在支付宝小程序里显示室内三维地图 需要满足的两个条件 调用ESMap室内地图需要用到小程序web-vi ...

  10. 1 .net中自定义事件的步骤

    1 申明一个自定义的类并且继承事件的基类 public class ClientSocketModelConnectedEvent:EventArgs { private string param; ...