自定义控件系列<第一篇>--多维表头

来源:互联网 发布:网络授权书制作免费 编辑:程序博客网 时间:2024/06/05 20:10

在NET中,自带的控件很多很强大,一般情况下是足够使用了。但是要满足客户需求和设计需求还是有些远远不够。

在显示数据表格或者操作数据表格的时候,我们往往会采用DataGridView控件去显示数据和操作数据。毕竟一般我们表格的基础功能,在这个控件中已经可以完美实现。

但是在外观方面,比如列标题只是显示一行。有时候我们设计时因为大量的不同数据内容显示在同一张表格中是比较凌乱的,此时需要有大标题和小标题让用户更直观的看清数据本身的归类。而自带的DataGridView控件中没办法这样实现,只能对控件外观进行重绘。

下面分段分析代码的步骤:
本代码主要运用函数:
Dictionary泛型(字典)
Draphics类(绘制)

自定义控件主要重写的三种方法

protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);//绘制界面}protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e){base.OnCellPainting(e);}//绘制表格属性protected override void OnCellClick(DataGridViewCellEventArgs e){base.OnCellClick(e);}//在单元格中单击

执行过程

输入第一个列索引,合并列数,大标题文本

 #region 二维表头之合并列        /// <param name="ColIndex">列的索引</param>        /// <param name="ColCount">需要合并的列数</param>        /// <param name="Text">合并列后的文本</param>        public void AddSpanHeader(int CoIindex, int CoICount, string Text)//合并列        {            if (CoIindex < 2)            {                throw new Exception("行宽应大于等于2,合并1列无意义");            }            else            {                //将小标题列加入大标题列中                int Right = CoIindex + CoICount - 1;//同一大标题下的最后一列的索引                TableRows[CoIindex] = new TableTou(Text, 1, CoIindex, Right);//添加标题下的最左列                TableRows[Right] = new TableTou(Text, 3, CoIindex, Right);//添加标题下的最右列                for (int i = CoIindex + 1; i < Right; i++)                {                    TableRows[i] = new TableTou(Text, 2, CoIindex, Right);//添加标题下的中间列                }            }        }#endregion 

选出需要合并的列,存入一个集合中Dictionary。

        #region 二维表头之需要合并的列存入Dictionary        private Dictionary<int, TableTou> TableRows = new Dictionary<int, TableTou>();        //二维键值数据        private struct TableTou        {            public TableTou(string Text, int Position, int Left, int Right)            {                this.Text = Text;//标题文本                this.Position = Position;//位置1左 2中 3右                this.Left = Left;//对应左边                this.Right = Right;//对应右边            }            public string Text;            public int Position;            public int Left;            public int Right;        }        #endregion     

重写绘制方法

以上程序把所有需要合并的列都存入Dictionary中,接下来绘制表格的列。
在OnCellPainting方法中发生

判断是否存在在Dictionary集合中

if (TableRows.ContainsKey(e.ColumnIndex))

代码如下:

 protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)//绘制表格属性        {            //e表示父类的表格            if (e.RowIndex == -1)            {                if (TableRows.ContainsKey(e.ColumnIndex))//判断如果键值中有此索引,则继续运行                {                    //画边框                    Graphics gp = e.Graphics;                    //单元格背景与边框                    e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);                    //表格标题单元格的X,Y坐标的宽度和高度                    int left = e.CellBounds.Left;//X轴                    int top = e.CellBounds.Top;//Y轴                    int right = e.CellBounds.Right; //y+宽度                    int bottom = e.CellBounds.Bottom; //x+高度                    //判断键值中的数据                    switch (TableRows[e.ColumnIndex].Position)                    {                        case 1:                            left += 2;//最左边                            break;                        case 2:                            break;                        case 3:                            right -= 2;//最右边                            break;                    }                    //画上半部分的底色                    gp.FillRectangle(new SolidBrush(e.CellStyle.BackColor),left,top,right-left,(bottom-top)/2);                    //画中线                    gp.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2, right, (top + bottom) / 2);                    //小标题                    StringFormat sf = new StringFormat();                    sf.LineAlignment = StringAlignment.Center;//垂直对齐                    sf.Alignment = StringAlignment.Center;//水平对齐                    gp.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black, new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);//小标题信息                    left = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Left, true).Left - 2;//获取当前列的X坐标                    if (left < 0)                    {                        left = this.GetCellDisplayRectangle(-1, -1, true).Width;                    }                    right = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Right, true).Right - 2;//获取当前列的Right                    if (right < 0)                    {                        right = this.Width;                    }                    //大标题                    gp.DrawString(TableRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black, new Rectangle(left, top, right - left, (bottom - top) / 2), sf);                    e.Handled = true;                }                      }            base.OnCellPainting(e);        }

这里写图片描述
全部代码如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.Linq;using System.Text;using System.Windows.Forms;using System.Drawing;namespace DataGridView隔行显示不同颜色之两种实现方法.YuanGon_GonNen{    public partial class YuanGo : DataGridView    {        public YuanGo()        {            InitializeComponent();        }        public YuanGo(IContainer container)        {            container.Add(this);            InitializeComponent();        }        //重写方法        protected override void OnPaint(PaintEventArgs e)//绘制界面        {            //在执行此方法的过程中发生的任何异常将被忽略            base.OnPaint(e);        }        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)//绘制表格属性        {            //e表示父类的表格            if (e.RowIndex == -1)            {                if (TableRows.ContainsKey(e.ColumnIndex))//判断如果键值中有此索引,则继续运行                {                    //画边框                    Graphics gp = e.Graphics;                    //单元格背景与边框                    e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);                    //表格标题单元格的X,Y坐标的宽度和高度                    int left = e.CellBounds.Left;//X轴                    int top = e.CellBounds.Top;//Y轴                    int right = e.CellBounds.Right; //y+宽度                    int bottom = e.CellBounds.Bottom; //x+高度                    switch (TableRows[e.ColumnIndex].Position)                    {                        case 1:                            left += 2;                            break;                        case 2:                            break;                        case 3:                            right -= 2;                            break;                    }                    //画上半部分的底色                    gp.FillRectangle(new SolidBrush(e.CellStyle.BackColor),left,top,right-left,(bottom-top)/2);                    //画中线                    gp.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2, right, (top + bottom) / 2);                    //小标题                    StringFormat sf = new StringFormat();                    sf.LineAlignment = StringAlignment.Center;//垂直对齐                    sf.Alignment = StringAlignment.Center;//水平对齐                    gp.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black, new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);//小标题信息                    left = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Left, true).Left - 2;//获取当前列的X坐标                    if (left < 0)                    {                        left = this.GetCellDisplayRectangle(-1, -1, true).Width;                    }                    right = this.GetColumnDisplayRectangle(TableRows[e.ColumnIndex].Right, true).Right - 2;//获取当前列的Right                    if (right < 0)                    {                        right = this.Width;                    }                    //大标题                    gp.DrawString(TableRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black, new Rectangle(left, top, right - left, (bottom - top) / 2), sf);                    e.Handled = true;                }                      }            base.OnCellPainting(e);        }        protected override void  OnCellClick(DataGridViewCellEventArgs e)//在单元格中单击        {            base.OnCellClick(e);        }        #region 二维表头的背景颜色        [Description("二维表头的背景颜色"),Browsable(true),Category("二维表头")]//在属性中显示这一栏        public Color ERBiaoTou        {            get{return _eRBiaoTou;}            set{_eRBiaoTou = value;}        }        #endregion        private Color _eRBiaoTou = System.Drawing.SystemColors.Window;        #region 需要合并的列存入Dictionary        #region 二维表头之表头信息        private Dictionary<int, TableTou> TableRows = new Dictionary<int, TableTou>();//需要二维表头的列        private struct TableTou//二维表头信息        {            public TableTou(string Text, int Position, int Left, int Right)            {                this.Text = Text;//标题文本                this.Position = Position;//位置1左 2中 3右                this.Left = Left;//对应左边                this.Right = Right;//对应右边            }            public string Text;            public int Position;            public int Left;            public int Right;        }        #endregion        #region 二维表头之合并列        /// <param name="ColIndex">列的索引</param>        /// <param name="ColCount">需要合并的列数</param>        /// <param name="Text">合并列后的文本</param>        public void AddSpanHeader(int CoIindex, int CoICount, string Text)//合并列        {            if (CoIindex < 2)            {                throw new Exception("行宽应大于等于2,合并1列无意义");            }            else            {                //将小标题列加入大标题列中                int Right = CoIindex + CoICount - 1;//同一大标题下的最后一列的索引                TableRows[CoIindex] = new TableTou(Text, 1, CoIindex, Right);//添加标题下的最左列                TableRows[Right] = new TableTou(Text, 3, CoIindex, Right);//添加标题下的最右列                for (int i = CoIindex + 1; i < Right; i++)                {                    TableRows[i] = new TableTou(Text, 2, CoIindex, Right);//添加标题下的中间列                }            }        }        #endregion         #endregion    }}

调用窗体代码

#region 绑定数据源            dataGridView1.AutoGenerateColumns = false;            dataGridView1.AutoSize = true;            dataGridView1.DataSource = Table();             #endregion            #region CheckBox列名                System.Windows.Forms.DataGridViewTextBoxColumn dgvcba = new DataGridViewTextBoxColumn();//登陆名列            dgvcba.HeaderText = "登录名";            dgvcba.Name = "columna";            dgvcba.ReadOnly = false;            dgvcba.SortMode = DataGridViewColumnSortMode.Programmatic;                      this.dataGridView1.Columns.Insert(0, dgvcba);            dgvcba.DataPropertyName = Table().Columns[0].ToString();            System.Windows.Forms.DataGridViewTextBoxColumn dgvcbb = new DataGridViewTextBoxColumn();//员工姓名列            dgvcbb.HeaderText = "员工姓名";            dgvcbb.Name = "columnb";            dgvcbb.ReadOnly = false;            dgvcbb.SortMode = DataGridViewColumnSortMode.Programmatic;            this.dataGridView1.Columns.Insert(1, dgvcbb);                       dgvcbb.DataPropertyName = Table().Columns[1].ToString();            //.......代码太长......            #endregion            this.dataGridView1.Dock = DockStyle.Fill;            this.dataGridView1.BackgroundColor = Color.White;            this.dataGridView1.AllowUserToAddRows = true;//是否显示新行            this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;            this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;            this.dataGridView1.ColumnHeadersHeight = 40;            this.dataGridView1.AddSpanHeader(2, 11, "员工享有权限");
1 0
原创粉丝点击