实现DataGridView的多层表头

来源:互联网 发布:utorrent for linux 编辑:程序博客网 时间:2024/05/01 16:04

因工作需要使用DataGridView实现多层表头的显示,在网上找了些实现的例子(在此感谢manimanihome的博文提供原始素材,需要看原理的请转过去查看),但在绘制时的计算逻辑上有些问题,自己经过了一些修改勉强可以满足需要了。

还存在的问题有:在拖动改变列宽后有时候字/线没有刷过来;鼠标在标题栏上移动时会不停的刷影响效果。

使用时需要注意3个地方:主要类包含MultiHead,MutiHeadDGV:DataGridView;

Datagridview的ColumnHeadersHeightSizeMode属性最好设为EnableResizing;

布局的列数需要与多层列的最低级标题数一致。

下面上代码:

MultiHead类

    class MultiHead    {        #region ...静态...        private static SortedList<string, int> cellPointX;        /// <summary>        /// 获取标题单元格的左边距        /// </summary>        /// <param name="rowindex"></param>        /// <param name="columnindex"></param>        /// <returns></returns>        private static int GetCellPointX(int rowindex, int columnindex)        {            string key = string.Format("{0}.{1}",rowindex,columnindex);            return cellPointX[key];        }        /// <summary>        /// 设置或更新标题单元格的左边距        /// </summary>        /// <param name="rowindex"></param>        /// <param name="columnindex"></param>        /// <param name="x"></param>        /// <returns></returns>        private static void SetCellPoint(int rowindex, int columnindex, int x)        {            if (cellPointX == null)                cellPointX = new SortedList<string, int>();            string key = string.Format("{0}.{1}", rowindex, columnindex);            if (cellPointX.ContainsKey(key))                cellPointX[key] = x;            else                cellPointX.Add(key, x);        }        #endregion        private DataGridView dataGridView;        public MultiHead(DataGridView grid)        {            this.dataGridView = grid;            string title = "";            for (int i = 0; i != this.dataGridView.Columns.Count - 1; ++i)            {                title += this.dataGridView.Columns[i].HeaderText + ",";            }            title = title.Substring(1, title.Length - 2);            this.titleHead = new string[] { title };        }        //通過构造函數來限制title的格式,始終与grid保持一致        public MultiHead(DataGridView grid, string[] title)        {            //grid不等于null            for (int i = 0; i != title.Length - 1; ++i)            {                string[] s = title[i].Split(',');                if (grid.Columns.Count == s.Length)                {                    continue;                }                else                {                    throw new Exception("title的元素個數与grid的欄位總數不一致.");                }            }            this.dataGridView = grid;            this.titleHead = title;        }        private string[] titleHead;        public string[] TitleHead        {            get            {                return titleHead;            }        }        public string Draw(DataGridViewCellPaintingEventArgs e)        {            string message = string.Empty;            if (e.RowIndex == -1)            {                using (                    Brush gridBrush = new SolidBrush(this.dataGridView.GridColor),                    backColorBrush = new SolidBrush(e.CellStyle.BackColor))                {                    using (Pen gridLinePen = new Pen(gridBrush))                    {                                                gridLinePen.Color = dataGridView.GridColor;                        if (e.ColumnIndex == -1)                        {                            e.Graphics.FillRectangle(backColorBrush, e.CellBounds);                            //畫右邊線                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);                            //畫bottom線                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1);                        }                        else                        {                            //第一行已经绘制的上一个标题                            string[] drawtitles = new string[titleHead.Length];                            for (int i = 0; i < titleHead.Length; ++i)//逐行畫                            {                                SetCellPoint(i, e.ColumnIndex,e.CellBounds.Width);                                int width;                                int height;                                int locationX;                                int locationY;                                int paintingwidth=0;                                                                string[] currRow = titleHead[i].Split(',');                                width = e.CellBounds.Width;                                //開始列                                int startColIndex = e.ColumnIndex;                                while (startColIndex > 0)                                {                                    if (currRow[e.ColumnIndex] == currRow[startColIndex - 1])                                    {                                        if (this.dataGridView.Columns[startColIndex - 1].Visible)                                        {                                            width += this.dataGridView.Columns[startColIndex - 1].Width;                                        }                                        if (startColIndex <= e.ColumnIndex)                                            paintingwidth += this.dataGridView.Columns[startColIndex].Width;                                        startColIndex--;                                    }                                    else                                    {                                                                                break;                                    }                                                                    }                                paintingwidth += GetCellPointX(i, startColIndex);                                //結束列                                int endColIndex = e.ColumnIndex;                                                                while (endColIndex < this.dataGridView.Columns.Count - 1)                                {                                    if (currRow[e.ColumnIndex] == currRow[endColIndex + 1])                                    {                                        if (this.dataGridView.Columns[endColIndex + 1].Visible)                                        {                                            width += this.dataGridView.Columns[endColIndex + 1].Width;                                                                                }                                        endColIndex++;                                    }                                    else                                    {                                        break;                                    }                                }                                height = e.CellBounds.Height / titleHead.Length;                                //開始行                                int startRowIndex = i;                                while (startRowIndex > 0)                                {                                    string[] overRow = titleHead[startRowIndex - 1].Split(',');                                    if (currRow[e.ColumnIndex] == overRow[e.ColumnIndex])                                    {                                        int overStartColIndex = e.ColumnIndex;                                        int overEndColIndex = e.ColumnIndex;                                        while (overStartColIndex > 0)                                        {                                            if (overRow[e.ColumnIndex] == currRow[overStartColIndex - 1])                                            {                                                overStartColIndex--;                                            }                                            else                                            {                                                break;                                            }                                        }                                        while (overEndColIndex < this.dataGridView.Columns.Count - 1)                                        {                                            if (overRow[e.ColumnIndex] == overRow[overEndColIndex + 1])                                            {                                                overEndColIndex++;                                            }                                            else                                            {                                                break;                                            }                                        }                                        if (startColIndex == overStartColIndex && endColIndex == overEndColIndex)                                        {                                            height += e.CellBounds.Height / titleHead.Length;                                            startRowIndex--;                                        }                                        else                                        {                                            break;                                        }                                    }                                    else                                    {                                        break;                                    }                                }                                //結束行                                int endRowIndex = i;                                while (endRowIndex < titleHead.Length - 1)                                {                                    string[] lowRow = titleHead[endRowIndex + 1].Split(',');                                    if (currRow[e.ColumnIndex] == lowRow[e.ColumnIndex])                                    {                                        int lowStartColIndex = e.ColumnIndex;                                        int lowEndColIndex = e.ColumnIndex;                                        while (lowStartColIndex > 0)                                        {                                            if (lowRow[e.ColumnIndex] == currRow[lowStartColIndex - 1])                                            {                                                lowStartColIndex--;                                            }                                            else                                            {                                                break;                                            }                                        }                                        while (lowEndColIndex < this.dataGridView.Columns.Count - 1)                                        {                                            if (lowRow[e.ColumnIndex] == lowRow[lowEndColIndex + 1])                                            {                                                lowEndColIndex++;                                            }                                            else                                            {                                                break;                                            }                                        }                                        if (startColIndex == lowStartColIndex && endColIndex == lowEndColIndex)                                        {                                            height += e.CellBounds.Height / titleHead.Length;                                            endRowIndex++;                                        }                                        else                                        {                                            break;                                        }                                    }                                    else                                    {                                        break;                                    }                                }                                locationX = e.CellBounds.Right - paintingwidth;//  e.CellBounds.Right - width;                                locationY = e.CellBounds.Bottom - (titleHead.Length - endRowIndex - 1) * e.CellBounds.Height / titleHead.Length - height;                                                                Rectangle recCell = new Rectangle(locationX, locationY, width, height);                                message += string.Format("{0}:({1},{2},{3},{4})\r\n", currRow[e.ColumnIndex], locationX, locationY, width, height);                                //erase cell                                e.Graphics.FillRectangle(backColorBrush, recCell);                                //畫right和bottom線                                e.Graphics.DrawLine(gridLinePen, locationX + width - 1, locationY - 1, locationX + width - 1, locationY + height - 1);                                e.Graphics.DrawLine(gridLinePen, locationX - 1, locationY + height - 1, locationX + width - 1, locationY + height - 1);                                                                //畫文字                                StringFormat sf = new StringFormat();                                sf.Alignment = StringAlignment.Center;                                sf.LineAlignment = StringAlignment.Center;                                e.Graphics.DrawString(currRow[e.ColumnIndex], e.CellStyle.Font, Brushes.Black, recCell, sf);                            }                        }                        e.Handled = true;                    }                }            }            return message;        }    }


MutiHeadDGV:DataGridView


    class MutiHeadDGV:DataGridView    {        private string[] titleHead;        public string[] TitleHead        {            get            {                return this.titleHead;            }            set            {                this.titleHead = value;            }        }        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)        {            titleHead = new string[] { "基础资料,基础资料,基础资料,基础资料,附加信息,附加信息,附加信息,附加信息,描述",                "姓名,籍贯,出生时间,性别,现住址,职业,收入,爱好,描述"};                            MultiHead m = new MultiHead(this, titleHead);        }    }

TitleHead属性<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">多层标题是可以在外部赋值的哦</strong>



0 0
原创粉丝点击