前几天Jo Muncher's Blog上看到《VS2005的DataGridView 多维合并标题 功能拓展》的文章,对我制作DataGridView多表头大有帮助,并把代码进行了调试,发现还有问题。近日把VB代码修改成C#代码,并对部分BUG进行修改,最终还是把问题攻克了,效果比较理想。见下图

源代码如下:

HeaderUnitView.cs

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 DataGridViewSampCs
...{
    public partial class HeaderUnitView : DataGridView
    ...{
        private TreeView[] _columnTreeView;
        private ArrayList _columnList = new ArrayList();
        private int _cellHeight = 17;
        private int _columnDeep = 1;
        

        /**//// <summary>
        /// 构造函数
        /// </summary>
        public HeaderUnitView()
        ...{
            InitializeComponent();
        }

        [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);
            /**/////写字段文本

            //e.Graphics.DrawString(node.Text
            //                        , this.Font
            //                        , Brushes.Black
            //                        , uhRectangle
            //                        , textFormat);
            e.Graphics.DrawString(node.Text, this.Font
                                    , Brushes.Black
                                    , 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);
        }

        /**////判断节点是否为单一的
        //private Boolean IsSingleChildNode(TreeNode node)
        //{
        //    if (node.Nodes == null)
        //        return false;

        //    if (node.Nodes.Count == 0)
        //        return false;

        //    if (node.Nodes.Count == 1)
        //        return true;
        //    return false;
        //}


        /**//// <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>
        /// <remarks></remarks>
        protected override void OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
        ...{
            //行标题不重写
            if (e.ColumnIndex < 0)
            ...{
                base.OnCellPainting(e);
                return;
            }

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

        
    }
}

HeaderUnitView.Designer.cs(修改Dispose事件中的代码,其它的不用修改)

         /**//// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        ...{
            if (_columnTreeView != null)
            ...{
                for (int i = 0; i <= _columnTreeView.Length - 1; i++)
                ...{
                    _columnTreeView[i].Dispose();
                }
            }

            if (disposing && (components != null))
            ...{
                components.Dispose();
            }
            base.Dispose(disposing);
        }

由于是Jo Muncher's 文章,这里不再多说了,如想知道更多,请点击下面连接。

http://blog.csdn.net/JoMuncher/archive/2007/11/02/1862977.aspx

转载于:https://www.cnblogs.com/hehuaflower/archive/2009/02/28/1400188.html

转:VS2005的DataGridView 多维合并标题 功能拓展相关推荐

  1. datagridview 纵向 横向 合并单元格

    datagridview 单元格合并:纵向以及横向合并参考了csdn上不知哪位的代码,具体哪位找不到连接了. 纵向合并: /// <summary>/// 纵向合并,即合并数据项的值/// ...

  2. c# winform datagridview单元格合并

    效果 /// <summary>     /// DataGridView 单元格合并信息     /// </summary>     public struct DataG ...

  3. smart 3D 中的block merge(空三合并)功能详细介绍

    声明:时隔一年之久没有继续更博,今日受疫情影响不能外出办公,浏览推送出来的博客,发现有笔友做了标题功能的叙述,大概看了下,做出一些补充,方便大家实际作业能够直接使用.同时,希望兄弟姐妹们响应号召,做好 ...

  4. Git将主合并到功能分支

    本文翻译自:Git merge master into feature branch Let's say we have the following situation in Git: 假设我们在Gi ...

  5. Office合并字符功能比较(转)

    本人经常喜欢关注Office方面的一些发展情况.今天就拿2家Office(金山和永中)的合并字符功能作下比较吧. 一些文档标题文字需要特殊标识时,就要用到合并字符功能,特别是一些政府机关单位的报告等. ...

  6. 二维彩虹产品功能更新(H5编辑二维码)

    二维彩虹的产品功能又又又又更新啦~ 此次 "H5编辑" 功能 更新如下: 1,标题模板 增加了更多可选择的标题模板.模板内文字可编辑,同时支持模板颜色编辑更新. 2,文本模板 正文 ...

  7. Android实现二维码扫描功能(一)ZXing插件接入

    简介 关于Android扫描二维码的功能实现,网上有很多相关资料.在对比之后,选用了前辈了修改过的ZXing直接接入到项目中,特制作此demo,介绍整个过程. (最新更新)本篇文章讲解的接入方法对部分 ...

  8. 计算机动画软件有哪些软件,终于清楚二维计算机动画软件功能介绍

    终于清楚二维计算机动画软件功能介绍 日期:2019-10-30 18:29:15 浏览:13 核心提示:二维计算机动画软件功能介绍动地完成更为复杂和繁琐的自动上色和中间帧自动生成等工作目前的计算机辅助 ...

  9. 奥维怎么记录沿线轨迹_奥维地图最新功能—北斗星盒轨迹实时分享

    原标题:奥维地图最新功能-北斗星盒轨迹实时分享 奥维互动地图新版本(V7.6.7)推出了又一强大功能--设备位置采集实时上传至奥维服务器,并把历史位置分享给指定好友. 听起来不知所云,下面小编就为越野 ...

最新文章

  1. 6.python探测Web服务质量方法之pycurl模块
  2. SQL Server 查询性能优化——堆表、碎片与索引(一)
  3. autumn 0.5.1 : Python Package Index
  4. Double 与 Float 的值的比較结果
  5. Lucene从入门到进阶(6.6.0版本)
  6. 停止FMS3.5的Apache服务
  7. 2019年总结【跨越今天,更不平凡】
  8. 银行界加强计算机病毒管理,银行计算机管理系统维护现状与对策研究(7.12).doc...
  9. kmp算法next计算方法_KMP 算法详解
  10. Android中如何做到Service被关闭后又自动启动
  11. 在gfs2中关闭selinux
  12. activiti idea 请假流程_使用idea进行activiti工作流开发入门学习
  13. ps怎么撤销参考线_Photoshop120条新手必备技巧
  14. 52个数据可视化图表鉴赏
  15. 软件需求规格说明书,概要设计说明书,详细设计说明书(文档)
  16. python爬虫学习之路1
  17. 20135323符运锦---信息安全系统设计基础第一周学习总结
  18. Jenkins docker下JNLP slave节点远程连接报错port not reachable的解决
  19. ubuntu18.04安装中中文输入法
  20. Android模拟器的ip获取以及模拟器之间socket通信

热门文章

  1. 阵列函数 java_Java复制阵列– Java中的阵列复制
  2. sql联接查询_SQL联接
  3. log4j.xml示例_log4j.xml示例配置
  4. python bytes_Python bytes()
  5. android 底边框_Android底表
  6. python面试问题_Python面试问题
  7. java中堆栈内存_Java堆空间与堆栈– Java中的内存分配
  8. 开课吧Java课程之详解文件输出流FileInputStream
  9. Lua中调用C/C++函数 (转)
  10. php for循环建数据