• 【Winform-自定义控件】 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");            }        }    }}

  • 相关阅读:
    $$Ctrl+shift+M分数罗马字母小写
    设置字体大小加粗斜体下划线
    无序列表有序列表
    数学公式插入
    文本居中、代码插入、图片插入
    VM 使用问题 | 安装失败->>注册表
    VM小技巧——虚拟机解决vm窗口太小的办法
    OneNet平台实践
    linux 打包 | autoconf 使用方法
    C 总结 | 复习注意点
  • 原文地址:https://www.cnblogs.com/Sukie-s-home/p/6526880.html
Copyright © 2020-2023  润新知