C#中DataGridView多層表頭的制作(2)

C#中DataGridView多層表頭的制作(2)

1.引言:
以前也做過一下多表頭,可是還不能使用.
http://blog.csdn.net/manimanihome/archive/2008/01/22/2058514.aspx

2.原理:
利用數組保存表頭信息,數組的格式有一定的限制,然后用CellPainting事件來重繪表頭.

3.實現:
本文在使用時,最好將ColumnHeadersHeightSizeMode設為DisableResizing,因為如果設成AutoSize,對于跨多列的表頭,在拖動分隔條調整列大小時,表頭文字顯示有重复或不完整的現象,需點擊一下表頭才顯示正常.

--1.首先做一個表頭類
MultiHead.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace CellPaintingDataGridView
{
    class MultiHead
    {
        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 void Draw(DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex == -1)
            {
                using (
                    Brush gridBrush = new SolidBrush(this.dataGridView.GridColor),
                    backColorBrush = new SolidBrush(e.CellStyle.BackColor))
                {
                    using (Pen gridLinePen = new Pen(gridBrush))
                    {

                        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
                        {
                         

                            for (int i = 0; i < titleHead.Length; ++i)//逐行畫
                            {
                                int width;
                                int height;
                                int locationX;
                                int locationY;

                                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;
                                        }
                                        startColIndex--;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                //結束列
                                int endColIndex = e.ColumnIndex;
                                while (endColIndex < this.dataGridView.Columns.Count - 1)
                                {
                                    if (currRow[e.ColumnIndex] == currRow[endColIndex + 1])
                                    {
                                        if (this.dataGridView.Columns[startColIndex + 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 - width;
                                locationY = e.CellBounds.Bottom - (titleHead.Length - endRowIndex - 1) * e.CellBounds.Height / titleHead.Length - height;

                                Rectangle recCell = new Rectangle(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;
                                e.Graphics.DrawString(currRow[e.ColumnIndex], e.CellStyle.Font, Brushes.Black, recCell, sf);


                            }
                        }

                        e.Handled = true;


                    }
                }
            }
        }

 

    }
}


--2.調用有二种方式,一种是直接在需要使用多行表頭的地方添加一個CellPainting事件(如示例1),也可以先重載一個DataGridView,這樣在設計時就可以看到效果(如示例2).

注意:最好將ColumnHeadersHeightSizeMode設為DisableResizing

示例1:
 string[] title = new string[]{"column,column,column,column3,column5",
                                        "colum1,colum1,成本,column3,column5",
                                        "colum1,colum2,成本,column,column5"
                                    };

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            MultiHead m = new MultiHead(this.dataGridView1, title);
            m.Draw(e);
 }

示例2:
DataGridViewEx.cs

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;

namespace CellPaintingDataGridView
{
    public partial class DataGridViewEx : DataGridView
    {
        public DataGridViewEx()
        {
            InitializeComponent();
        }

        public DataGridViewEx(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        private string[] titleHead;
        public string[] TitleHead
        {
            get
            {
                return this.titleHead;
            }
            set
            {
                this.titleHead = value;
            }
        }
 

        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            MultiHead m = new MultiHead(this, titleHead);
            m.Draw(e);

        }
       
    }
}

4.思考
其實做多表頭,用tree來做更合适一些,但沒有想到較滿意的做法,主要是支持設計時的可視化.以下是一個用tree來做的多表頭,雖然有點不規范,但還算實現了效果,可以參考.
(VB實現) http://blog.csdn.net/JoMuncher/archive/2007/11/02/1862977.aspx
(C#實現) http://blog.csdn.net/teacatcn/archive/2008/01/23/2060482.aspx

其實,我的想法是做一個TreeNodeCollection集合屬性,可是在實做時沒有成功,還望各位网友指教.

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值