编程语言
首页 > 编程语言> > C#真正意义上的用DataGridView合并表头以及表格

C#真正意义上的用DataGridView合并表头以及表格

作者:互联网

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace SGTool.Controls
{
    // colum map : colum and RowPairDic
    using ColumPairDic = Dictionary<int, Dictionary<int, int>>;
    // rows map in a colum : startRow, endRow
    using RowPairDic = Dictionary<int, int>;
    public class HeaderInfo
    {
        public class HeaderCellBorderInfo
        {
            public bool Top;
            public bool Left;
            public bool Right;
            public bool Bottom;
        }
        public HeaderInfo(int rowCount, int colCount, List<HeaderCellInfo> headerCellInfoList)
        {
            RowCount = rowCount;
            ColCount = colCount;
            HeaderCellInfoList = headerCellInfoList;
            InitHeaderInfo();
        }
        private void InitHeaderInfo()
        {
            CellNames = new string[RowCount, ColCount];
            CellBorders = new HeaderCellBorderInfo[RowCount, ColCount];
            Alignments = new DataGridViewContentAlignment[RowCount, ColCount];
            CellCrosses = new Rectangle[RowCount, ColCount];
            for (int i = 0; i < RowCount; i++)
            {
                for (int j = 0; j < ColCount; j++)
                {
                    CellNames[i, j] = string.Empty;
                    CellBorders[i, j] = new HeaderCellBorderInfo();
                    Alignments[i, j] = DataGridViewContentAlignment.MiddleCenter;
                }
            }
            for (int i = 0; i < RowCount; i++)
            {
                CellBorders[i, 0].Left = true;
                CellBorders[i, ColCount - 1].Right = true;
            }
            for (int j = 0; j < ColCount; j++)
            {
                CellBorders[0, j].Top = true;
                CellBorders[RowCount - 1, j].Bottom = true;
            }
            foreach (HeaderCellInfo headerCellInfo in HeaderCellInfoList)
            {
                for (int i = headerCellInfo.Row; i < headerCellInfo.Row + headerCellInfo.RowSpan; i++)
                {
                    for (int j = headerCellInfo.Col; j < headerCellInfo.Col + headerCellInfo.ColSpan; j++)
                    {
                        CellNames[i, j] = headerCellInfo.CellName;
                        Alignments[i, j] = headerCellInfo.Alignment;
                        CellCrosses[i, j].X = headerCellInfo.Col;
                        CellCrosses[i, j].Y = headerCellInfo.Row;
                        CellCrosses[i, j].Width = headerCellInfo.ColSpan;
                        CellCrosses[i, j].Height = headerCellInfo.RowSpan;
                    }
                }
                for (int i = headerCellInfo.Row; i < headerCellInfo.Row + headerCellInfo.RowSpan; i++)
                {
                    CellBorders[i, headerCellInfo.Col + headerCellInfo.ColSpan - 1].Right = true;
                }
                for (int j = headerCellInfo.Col; j < headerCellInfo.Col + headerCellInfo.ColSpan; j++)
                {
                    CellBorders[headerCellInfo.Row + headerCellInfo.RowSpan - 1, j].Bottom = true;
                }
            }
        }
        public int RowCount;
        public int ColCount;
        public string[,] CellNames;
        public HeaderCellBorderInfo[,] CellBorders;
        public DataGridViewContentAlignment[,] Alignments;
        public Rectangle[,] CellCrosses;
        public List<HeaderCellInfo> HeaderCellInfoList;
    }
    public class HeaderCellInfo
    {
        public HeaderCellInfo()
        {
        }
        public HeaderCellInfo(int row, int col, string cellName)
        {
            Row = row;
            Col = col;
            CellName = cellName;
        }
        public HeaderCellInfo(int row, int col, int rowSpan, int colSpan, string cellName)
        {
            Row = row;
            Col = col;
            RowSpan = rowSpan;
            ColSpan = colSpan;
            CellName = cellName;
        }
        public HeaderCellInfo(int row, int col, string cellName, DataGridViewContentAlignment alignment)
        {
            Row = row;
            Col = col;
            CellName = cellName;
            Alignment = alignment;
        }
        public HeaderCellInfo(int row, int col, int rowSpan, int colSpan, string cellName, DataGridViewContentAlignment alignment)
        {
            Row = row;
            Col = col;
            RowSpan = rowSpan;
            ColSpan = colSpan;
            CellName = cellName;
            Alignment = alignment;
        }
        public int Row;
        public int Col;
        public int RowSpan = 1;
        public int ColSpan = 1;
        public string CellName = string.Empty;
        public DataGridViewContentAlignment Alignment = DataGridViewContentAlignment.MiddleCenter;
    }
    public class HeaderSetting
    {
        private int _rowCount;
        public int RowCount
        {
            get { return _rowCount; }
            set { _rowCount = value; }
        }
        private int _colCount;
        public int ColCount
        {
            get { return _colCount; }
            set { _colCount = value; }
        }
        private List<HeaderCellInfo> _headerCellInfoList = new List<HeaderCellInfo>();
        public List<HeaderCellInfo> HeaderCellInfoList
        {
            get { return _headerCellInfoList; }
            set { _headerCellInfoList = value; }
        }
    }
    public partial class DataGridViewCellMerge : DataGridView
    {
        public DataGridViewCellMerge()
        {
            InitializeComponent();
            this.RowHeadersVisible = false;
            //this.ColumnHeadersVisible = false;
            this.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
            this.AllowUserToAddRows = false;
            this.MultiSelect = false;
            this.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
        }
        // merged rows with same value in a colum
        private ColumPairDic columDic = new ColumPairDic();
        // header info
        private HeaderInfo _headerInfo;
        // the rule of how to merge cell
        public ColumPairDic MergedRule
        {
            set { columDic = value; }
        }
        // header info
        public HeaderInfo HeaderInfo
        {
            set
            {
                _headerInfo = value;
            }
        }
        private string _headerInfoString;
        [Editor("System.ComponentModel.Design.MultilineStringEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        public string HeaderInfoString
        {
            get
            {
                return _headerInfoString;
            }
            set
            {
                _headerInfoString = value;
                try
                {
                    using (StringReader stringReader = new StringReader(_headerInfoString))
                    {
                        XmlSerializer xmlSerializer = new XmlSerializer(typeof(HeaderSetting));
                        HeaderSetting headerSetting = (HeaderSetting)xmlSerializer.Deserialize(stringReader);
                        if (headerSetting == null)
                        {
                            return;
                        }
                        HeaderInfo = new HeaderInfo(headerSetting.RowCount,
                            headerSetting.ColCount,
                            headerSetting.HeaderCellInfoList);
                    }
                }
                catch
                {
                }
            }
        }
        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            try
            {
                if (e.RowIndex == -1)
                {
                    PaintHeader(e);
                }
                else
                {
                    PaintCell(e);
                }
            }
            catch
            {
            }
            base.OnCellPainting(e);
        }
        // add all the index of merged rows into a list
        private List<int> GetMergedRows(RowPairDic rowDic)
        {
            List<int> rowList = new List<int>();
            Dictionary<int, int>.KeyCollection keys = rowDic.Keys;
            foreach (int key in keys)
            {
                int startRow = -1;
                int endRow = -1;
                startRow = key;
                rowDic.TryGetValue(key, out endRow);
                for (int row = startRow; row < endRow + 1; row++)
                {
                    rowList.Add(row);
                }
            }
            return rowList;
        }
        private void PaintCell(DataGridViewCellPaintingEventArgs e)
        {
            e.CellStyle.SelectionForeColor = e.CellStyle.ForeColor;
            e.CellStyle.SelectionBackColor = e.CellStyle.BackColor;
            bool normalCell = true;
            if (columDic.ContainsKey(e.ColumnIndex))
            {
                // the colum contains some merged cells
                RowPairDic rowDic = new RowPairDic();
                columDic.TryGetValue(e.ColumnIndex, out rowDic);
                if (rowDic.Count != 0)
                {
                    // get all the merged row in a colum
                    List<int> rowList = GetMergedRows(rowDic);
                    if (rowList.Contains(e.RowIndex))
                    {
                        normalCell = false;
                        e.PaintBackground(e.ClipBounds, false);
                        // the cell is the first row of the merged cells
                        if (rowDic.ContainsKey(e.RowIndex))
                        {
                            // paint the info
                            e.PaintContent(e.ClipBounds);
                        }
                        //  the cell is a merged cell
                        if (rowDic.ContainsValue(e.RowIndex))
                        {
                            // the cell is the end row of the merged cells
                            // draw the line under the cell
                            e.Graphics.DrawLine(new Pen(this.GridColor), e.CellBounds.Left, e.CellBounds.Bottom - 1,
                                e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
                        }
                        else
                        {
                            // the cell is NOT the end row of the merged cells
                            // clear the line under the cell
                            e.Graphics.DrawLine(new Pen(e.CellStyle.BackColor), e.CellBounds.Left, e.CellBounds.Bottom - 1,
                                e.CellBounds.Right - 2, e.CellBounds.Bottom - 1);
                        }
                    }
                }// end of if (rowDic.Count != 0)
            } // end of if (columDic.ContainsKey(e.ColumnIndex))
            if (normalCell)
            {
                e.PaintBackground(e.ClipBounds, false);
                e.PaintContent(e.ClipBounds);
            }
            e.Handled = true;
        }// e
        private void PaintHeader(DataGridViewCellPaintingEventArgs e)
        {
            // head line
            if (_headerInfo == null)
            {
                return;
            }
            int[] rowTops = new int[_headerInfo.RowCount];
            int[] rowBottoms = new int[_headerInfo.RowCount];
            rowTops[0] = e.CellBounds.Top;
            for (int i = 1; i < _headerInfo.RowCount; i++)
            {
                rowTops[i] = e.CellBounds.Height * i / _headerInfo.RowCount + rowTops[0];
            }
            rowBottoms[_headerInfo.RowCount - 1] = e.CellBounds.Bottom;
            for (int i = 0; i < _headerInfo.RowCount - 1; i++)
            {
                rowBottoms[i] = rowTops[i + 1];
            }
            for (int i = 0; i < _headerInfo.RowCount; i++)
            {
                PaintHeaderCellBackground(
                    e,
                    _headerInfo.CellBorders[i, e.ColumnIndex],
                    e.CellBounds.Left,
                    rowTops[i],
                    e.CellBounds.Right,
                    rowBottoms[i]);
            }
            for (int i = 0; i < _headerInfo.RowCount; i++)
            {
                Rectangle cross = _headerInfo.CellCrosses[i, e.ColumnIndex];
                int x2 = e.CellBounds.Left;
                if (x2 < 2)
                {
                    x2++;
                }
                int w2=0;
                for (int col = cross.X; col < cross.Width + cross.X;col ++)
                {
                    w2 += this.Columns[col].Width;
                    if (col < e.ColumnIndex)
                    {
                        x2 -= this.Columns[col].Width;
                    }
                }
                //int x = this.GetCellDisplayRectangle(cross.X, -1, true).X;
                int y = rowTops[cross.Y];
                //int width = this.GetCellDisplayRectangle(cross.X + cross.Width - 1, -1, true).X +
                //    this.GetCellDisplayRectangle(cross.X + cross.Width - 1, -1, true).Width - x;
                int height = rowBottoms[cross.Y + cross.Height - 1] - y;
                PaintHeaderCellContent(
                    e,
                    _headerInfo.CellNames[i, e.ColumnIndex],
                    x2,//x,
                    y,
                    w2,//width,
                    height,
                    _headerInfo.Alignments[i, e.ColumnIndex]);
            }
            e.Handled = true;
        }
        private void PaintHeaderCellBackground(DataGridViewCellPaintingEventArgs e, HeaderInfo.HeaderCellBorderInfo border, int left, int top, int right, int bottom)
        {
            Brush brushBack = new SolidBrush(this.ColumnHeadersDefaultCellStyle.BackColor);
            e.Graphics.FillRectangle(brushBack, left, top, right - left, bottom - top);
            right--;
            bottom--;
            Pen penGrid = new Pen(this.GridColor);
            if (border.Top)
            {
                e.Graphics.DrawLine(penGrid, left, top, right, top);
            }
            if (border.Left)
            {
                e.Graphics.DrawLine(penGrid, left, top, left, bottom);
            }
            if (border.Right)
            {
                e.Graphics.DrawLine(penGrid, right, top, right, bottom);
            }
            if (border.Bottom)
            {
                e.Graphics.DrawLine(penGrid, left, bottom, right, bottom);
            }
        }
        private void PaintHeaderCellContent(DataGridViewCellPaintingEventArgs e,
            string colName,
            int x, int y, int width, int height,
            DataGridViewContentAlignment alignment)
        {
            StringFormat drawFormat = new StringFormat();
            drawFormat.Alignment = StringAlignment.Center;
            drawFormat.LineAlignment = StringAlignment.Center;
            if (alignment == DataGridViewContentAlignment.MiddleLeft)
            {
                drawFormat.Alignment = StringAlignment.Near;
            }
            e.Graphics.DrawString(colName,
                this.Font,
                new SolidBrush(e.CellStyle.ForeColor),
                new RectangleF(x, y, width, height), drawFormat);
            //e.Graphics.DrawRectangle(Pens.Red, x, y, width, height);
            //e.Graphics.DrawRectangle(Pens.Yellow, x + 1, y + 1, width - 2, height - 2);
        }
        /// <summary>
        /// Unite Cells
        /// </summary>
        /// <param name="startRow"> start row index </param>
        /// <param name="endRow"> end row index </param>
        /// <param name="endCol"> columnIndex </param>
        public void UniteCells(int startRow, int endRow, int columnIndex)
        {
            RowPairDic rowPairDic = new RowPairDic();
            if (startRow > endRow)
            {
                return;
            }
            rowPairDic.Add(startRow, endRow);
            columDic.Add(columnIndex, rowPairDic);
        }
    }// end of class 
}// end of names

 

标签:RowCount,C#,headerCellInfo,表头,DataGridView,int,new,public,row
来源: https://www.cnblogs.com/dzjl/p/16189853.html