zoukankan      html  css  js  c++  java
  • Datagridview 实现二维表头和行合并

        using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Drawing;
        using System.Drawing.Design;
        using System.Windows.Forms;
    
        /// <summary>
        /// DataGridView行合并.请对属性MergeColumnNames 赋值既可
        /// </summary>
        public partial class RowMergeView : DataGridView
        {
            #region 构造函数
            public RowMergeView()
            {
                SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
                UpdateStyles();
                InitializeComponent();
            }
            #endregion
            #region 重写的事件
            protected override void OnPaint(PaintEventArgs pe)
            {
                // TODO: 在此处添加自定义绘制代码
    
                // 调用基类 OnPaint
                base.OnPaint(pe);
            }
            protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
            {
                try
                {
                    if (e.RowIndex > -1 && e.ColumnIndex > -1)
                    {
                        DrawCell(e);
                    }
                    else
                    {
                        //二维表头
                        if (e.RowIndex == -1)
                        {
                            if (SpanRows.ContainsKey(e.ColumnIndex)) //被合并的列
                            {
                                //画边框
                                Graphics g = e.Graphics;
                                e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
    
                                int left = e.CellBounds.Left, top = e.CellBounds.Top + 2,
                                right = e.CellBounds.Right, bottom = e.CellBounds.Bottom;
    
                                switch (SpanRows[e.ColumnIndex].Position)
                                {
                                    case 1:
                                        left += 2;
                                        break;
                                    case 2:
                                        break;
                                    case 3:
                                        right -= 2;
                                        break;
                                }
    
                                //画上半部分底色
                                g.FillRectangle(new SolidBrush(this._mergecolumnheaderbackcolor), left, top,
                                right - left, (bottom - top) / 2);
    
                                //画中线
                                g.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2,
                                right, (top + bottom) / 2);
    
                                //写小标题
                                var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
    
                                g.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black,
                                new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);
                                left = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Left, true).Left - 2;
    
                                if (left < 0) left = this.GetCellDisplayRectangle(-1, -1, true).Width;
                                right = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Right, true).Right - 2;
                                if (right < 0) right = this.Width;
    
                                g.DrawString(SpanRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black,
                                new Rectangle(left, top, right - left, (bottom - top) / 2), sf);
                                e.Handled = true;
                            }
                        }
                    }
                    base.OnCellPainting(e);
                }
                catch
                { }
            }
    
            protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
            {
                if (this.RowHeadersVisible)
                {
                    var rectangle = new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, this.RowHeadersWidth - 4, e.RowBounds.Height);
    
                    TextRenderer.DrawText(e.Graphics,
                        (e.RowIndex + 1).ToString(),
                        this.RowHeadersDefaultCellStyle.Font,
                        rectangle,
                        this.RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
                }
    
                base.OnRowPostPaint(e);
            }
    
            protected override void OnScroll(ScrollEventArgs e)
            {
                if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)// && e.Type == ScrollEventType.EndScroll)
                {
                    timer1.Enabled = false;
                    timer1.Enabled = true;
                }
            }
    
            #endregion
            #region 自定义方法
            /// <summary>
            /// 画单元格
            /// </summary>
            /// <param name="e"></param>
            private void DrawCell(DataGridViewCellPaintingEventArgs e)
            {
                if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet)
                {
                    e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                }
                Brush gridBrush = new SolidBrush(this.GridColor);
                var backBrush = new SolidBrush(e.CellStyle.BackColor);
                var fontBrush = new SolidBrush(e.CellStyle.ForeColor);
                //上面相同的行数
                int UpRows = 0;
                //下面相同的行数
                int DownRows = 0;
                //总行数
                int count = 0;
                if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -1)
                {
                    int cellwidth = e.CellBounds.Width;
                    var gridLinePen = new Pen(gridBrush);
                    string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
                    string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? "" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim();
                    if (!string.IsNullOrEmpty(curValue))
                    {
                        #region 获取下面的行数
                        for (int i = e.RowIndex; i < this.Rows.Count; i++)
                        {
                            if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
                            {
                                //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
    
                                DownRows++;
                                if (e.RowIndex != i)
                                {
                                    cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        #endregion
                        #region 获取上面的行数
                        for (int i = e.RowIndex; i >= 0; i--)
                        {
                            if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
                            {
                                //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
                                UpRows++;
                                if (e.RowIndex != i)
                                {
                                    cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        #endregion
                        count = DownRows + UpRows - 1;
                        if (count < 2)
                        {
                            return;
                        }
                    }
                    if (this.Rows[e.RowIndex].Selected)
                    {
                        backBrush.Color = e.CellStyle.SelectionBackColor;
                        fontBrush.Color = e.CellStyle.SelectionForeColor;
                    }
                    //以背景色填充
                    e.Graphics.FillRectangle(backBrush, e.CellBounds);
                    //画字符串
                    PaintingFont(e, cellwidth, UpRows, DownRows, count);
                    if (DownRows == 1)
                    {
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
                        count = 0;
                    }
                    // 画右边线
                    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);
    
                    e.Handled = true;
                }
            }
            /// <summary>
            /// 画字符串
            /// </summary>
            /// <param name="e"></param>
            /// <param name="cellwidth"></param>
            /// <param name="UpRows"></param>
            /// <param name="DownRows"></param>
            /// <param name="count"></param>
            private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count)
            {
                var fontBrush = new SolidBrush(e.CellStyle.ForeColor);
                var fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
                var fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
                int cellheight = e.CellBounds.Height;
    
                if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y + cellheight * DownRows - fontheight);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1));
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1));
                }
                else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight)
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1));
                }
                else
                {
                    e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
                }
            }
            #endregion
            #region 属性
            /// <summary>
            /// 设置或获取合并列的集合
            /// </summary>
            [MergableProperty(false)]
            [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
            [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
            [Localizable(true)]
            [Description("设置或获取合并列的集合"), Browsable(true), Category("单元格合并")]
            public List<string> MergeColumnNames
            {
                get
                {
                    return _mergecolumnname;
                }
                set
                {
                    _mergecolumnname = value;
                }
            }
            private List<string> _mergecolumnname = new List<string>();
            #endregion
            #region 二维表头
            private struct SpanInfo //表头信息
            {
                public SpanInfo(string Text, int Position, int Left, int Right)
                {
                    this.Text = Text;
                    this.Position = Position;
                    this.Left = Left;
                    this.Right = Right;
                }
    
                public readonly string Text; //列主标题
                public readonly int Position; //位置,1:左,2中,3右
                public readonly int Left; //对应左行
                public readonly int Right; //对应右行
            }
            private readonly Dictionary<int, SpanInfo> SpanRows = new Dictionary<int, SpanInfo>();//需要2维表头的列
            /// <summary>
            /// 合并列
            /// </summary>
            /// <param name="ColIndex">列的索引</param>
            /// <param name="ColCount">需要合并的列数</param>
            /// <param name="Text">合并列后的文本</param>
            public void AddSpanHeader(int ColIndex, int ColCount, string Text)
            {
                if (ColCount < 2)
                {
                    throw new Exception("行宽应大于等于2,合并1列无意义。");
                }
                //将这些列加入列表
                int Right = ColIndex + ColCount - 1; //同一大标题下的最后一列的索引
                SpanRows[ColIndex] = new SpanInfo(Text, 1, ColIndex, Right); //添加标题下的最左列
                SpanRows[Right] = new SpanInfo(Text, 3, ColIndex, Right); //添加该标题下的最右列
                for (int i = ColIndex + 1; i < Right; i++) //中间的列
                {
                    SpanRows[i] = new SpanInfo(Text, 2, ColIndex, Right);
                }
            }
            /// <summary>
            /// 清除合并的列
            /// </summary>
            public void ClearSpanInfo()
            {
                SpanRows.Clear();
                //ReDrawHead();
            }
    
            //刷新显示表头
            public void ReDrawHead()
            {
                foreach (int si in SpanRows.Keys)
                {
                    this.Invalidate(this.GetCellDisplayRectangle(si - 1, -1, true));
                }
            }
            private void timer1_Tick(object sender, EventArgs e)
            {
                timer1.Enabled = false;
                ReDrawHead();
            }
            /// <summary>
            /// 二维表头的背景颜色
            /// </summary>
            [Description("二维表头的背景颜色"), Browsable(true), Category("二维表头")]
            public Color MergeColumnHeaderBackColor
            {
                get { return this._mergecolumnheaderbackcolor; }
                set { this._mergecolumnheaderbackcolor = value; }
            }
            private Color _mergecolumnheaderbackcolor = System.Drawing.SystemColors.Control;
            #endregion
        }
    

      需要新建一个组件类,拖放一个timer,你也可以不使用timer,直接把timer里面的方法放到调用的地方

    使用:

           DataTable dt = new DataTable();
                dt.Columns.Add("1");
                dt.Columns.Add("2");
                dt.Columns.Add("3");
                dt.Columns.Add("4");
                dt.Rows.Add("中国", "上海", "5000", "7000");
                dt.Rows.Add("中国", "北京", "3000", "5600");
                dt.Rows.Add("美国", "纽约", "6000", "8600");
                dt.Rows.Add("美国", "华劢顿", "8000", "9000");
                dt.Rows.Add("英国", "伦敦", "7000", "8800");
                this.rowMergeView1.DataSource = dt;
                this.rowMergeView1.ColumnHeadersHeight = 40;
                this.rowMergeView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
                this.rowMergeView1.MergeColumnNames.Add("Column1");
                this.rowMergeView1.AddSpanHeader(2, 2, "XXXX");
    

      PS:http://www.cnblogs.com/greatverve/archive/2012/03/05/multi-datagridview.html

    缺点:只能二维,不能多维

  • 相关阅读:
    POJ 2752 Seek the Name, Seek the Fame
    POJ 2406 Power Strings
    KMP 算法总结
    SGU 275 To xor or not to xor
    hihocoder 1196 高斯消元.二
    hihoCoder 1195 高斯消元.一
    UvaLive 5026 Building Roads
    HDU 2196 computer
    Notions of Flow Networks and Flows
    C/C++代码中的笔误
  • 原文地址:https://www.cnblogs.com/tewuapple/p/2671560.html
Copyright © 2011-2022 走看看