locked
how to merge headers in a DataGridView RRS feed

  • Question

  • Hi,all

    Can someone tell me how to merge headers in a DataGridView to have this appearance?

     

    Department

    Employee

    Department  ID

    Department  Name

    Employee ID

    Employee Name

     Age

     

     

     

     

     

     

     

     

     

     

     

     



    Any help would be highly appreciated.
    Friday, April 6, 2007 8:35 AM

Answers

  • Hi, Constantine

    You can handle the CellPainting and Painting events of the DataGridView to custom draw the column header in the way you like. Below is a sample I wrote before on how to do this. Hope it helps.

    Code Snippet

    namespace Sample5

    {

        public partial class DgvColumnHeaderMerge : Form

        {

            public DgvColumnHeaderMerge()

            {

                InitializeComponent();

            }

     

            private void DgvColumnHeaderMerge_Load(object sender, EventArgs e)

            {

                this.dataGridView1.Columns.Add("JanWin", "Win");

                this.dataGridView1.Columns.Add("JanLoss", "Loss");

                this.dataGridView1.Columns.Add("FebWin", "Win");

                this.dataGridView1.Columns.Add("FebLoss", "Loss");

                this.dataGridView1.Columns.Add("MarWin", "Win");

                this.dataGridView1.Columns.Add("MarLoss", "Loss");

                this.dataGridView1.Columns.Add("AprWin", "Win");

                this.dataGridView1.Columns.Add("AprLoss", "Loss");

                this.dataGridView1.Columns.Add("MayWin", "Win");

                this.dataGridView1.Columns.Add("MayLoss", "Loss");

     

                for (int j = 0; j < this.dataGridView1.ColumnCount; j++)

                {

                    this.dataGridView1.Columns[j].Width = 45;

                }

                this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;

                this.dataGridView1.ColumnHeadersHeight = this.dataGridView1.ColumnHeadersHeight * 2;

                this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;

                this.dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);

                this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);

     

                this.dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

                this.dataGridView1.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView1_ColumnWidthChanged);

            }

     

            void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)

            {

                Rectangle rtHeader = this.dataGridView1.DisplayRectangle;

                rtHeader.Height = this.dataGridView1.ColumnHeadersHeight / 2;

                this.dataGridView1.Invalidate(rtHeader);

            }

     

            void dataGridView1_Scroll(object sender, ScrollEventArgs e)

            {

                Rectangle rtHeader = this.dataGridView1.DisplayRectangle;

                rtHeader.Height = this.dataGridView1.ColumnHeadersHeight / 2;

                this.dataGridView1.Invalidate(rtHeader);

            }

     

            void dataGridView1_Paint(object sender, PaintEventArgs e)

            {

                string[] monthes = { "January", "February", "March","April" ,"May"};

                for (int j = 0; j < 10;)

                {

                    Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1,true);

                    int w2 = this.dataGridView1.GetCellDisplayRectangle(j + 1, -1, true).Width;

                    r1.X += 1;

                    r1.Y += 1;

                    r1.Width = r1.Width + w2 - 2;

                    r1.Height = r1.Height / 2 - 2;

                    e.Graphics.FillRectangle(new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

                    StringFormat format = new StringFormat();

                    format.Alignment = StringAlignment.Center;

                    format.LineAlignment = StringAlignment.Center;

                    e.Graphics.DrawString(monthes[j/2],

                        this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,

                        new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),

                        r1,

                        format);

                    j += 2;

                }

            }

     

            void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            {

                if (e.RowIndex == -1 && e.ColumnIndex > -1)

                {

                    Rectangle r2 = e.CellBounds;

                    r2.Y += e.CellBounds.Height / 2;

                    r2.Height = e.CellBounds.Height / 2;

     

                    e.PaintBackground(r2, true);

                   

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

        }

    }

     

    Friday, April 6, 2007 8:46 AM

All replies

  • Hi, Constantine

    You can handle the CellPainting and Painting events of the DataGridView to custom draw the column header in the way you like. Below is a sample I wrote before on how to do this. Hope it helps.

    Code Snippet

    namespace Sample5

    {

        public partial class DgvColumnHeaderMerge : Form

        {

            public DgvColumnHeaderMerge()

            {

                InitializeComponent();

            }

     

            private void DgvColumnHeaderMerge_Load(object sender, EventArgs e)

            {

                this.dataGridView1.Columns.Add("JanWin", "Win");

                this.dataGridView1.Columns.Add("JanLoss", "Loss");

                this.dataGridView1.Columns.Add("FebWin", "Win");

                this.dataGridView1.Columns.Add("FebLoss", "Loss");

                this.dataGridView1.Columns.Add("MarWin", "Win");

                this.dataGridView1.Columns.Add("MarLoss", "Loss");

                this.dataGridView1.Columns.Add("AprWin", "Win");

                this.dataGridView1.Columns.Add("AprLoss", "Loss");

                this.dataGridView1.Columns.Add("MayWin", "Win");

                this.dataGridView1.Columns.Add("MayLoss", "Loss");

     

                for (int j = 0; j < this.dataGridView1.ColumnCount; j++)

                {

                    this.dataGridView1.Columns[j].Width = 45;

                }

                this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;

                this.dataGridView1.ColumnHeadersHeight = this.dataGridView1.ColumnHeadersHeight * 2;

                this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;

                this.dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);

                this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);

     

                this.dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

                this.dataGridView1.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView1_ColumnWidthChanged);

            }

     

            void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)

            {

                Rectangle rtHeader = this.dataGridView1.DisplayRectangle;

                rtHeader.Height = this.dataGridView1.ColumnHeadersHeight / 2;

                this.dataGridView1.Invalidate(rtHeader);

            }

     

            void dataGridView1_Scroll(object sender, ScrollEventArgs e)

            {

                Rectangle rtHeader = this.dataGridView1.DisplayRectangle;

                rtHeader.Height = this.dataGridView1.ColumnHeadersHeight / 2;

                this.dataGridView1.Invalidate(rtHeader);

            }

     

            void dataGridView1_Paint(object sender, PaintEventArgs e)

            {

                string[] monthes = { "January", "February", "March","April" ,"May"};

                for (int j = 0; j < 10;)

                {

                    Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1,true);

                    int w2 = this.dataGridView1.GetCellDisplayRectangle(j + 1, -1, true).Width;

                    r1.X += 1;

                    r1.Y += 1;

                    r1.Width = r1.Width + w2 - 2;

                    r1.Height = r1.Height / 2 - 2;

                    e.Graphics.FillRectangle(new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);

                    StringFormat format = new StringFormat();

                    format.Alignment = StringAlignment.Center;

                    format.LineAlignment = StringAlignment.Center;

                    e.Graphics.DrawString(monthes[j/2],

                        this.dataGridView1.ColumnHeadersDefaultCellStyle.Font,

                        new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor),

                        r1,

                        format);

                    j += 2;

                }

            }

     

            void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            {

                if (e.RowIndex == -1 && e.ColumnIndex > -1)

                {

                    Rectangle r2 = e.CellBounds;

                    r2.Y += e.CellBounds.Height / 2;

                    r2.Height = e.CellBounds.Height / 2;

     

                    e.PaintBackground(r2, true);

                   

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

        }

    }

     

    Friday, April 6, 2007 8:46 AM
  • Thanks for the reply.
    Your codes are working fine.
    thanks Zhi-Xin!
    Friday, April 6, 2007 3:13 PM
  • I used this code with datagridview.dock set to fill my form. When I resize the form the custom header rectangles added in your code that have the months, have vertical lines in them, do not render properly. Do you have a solution please?

     

    -Scott

    • Proposed as answer by Morin Johnny Wednesday, December 17, 2008 10:04 AM
    Saturday, January 5, 2008 5:17 PM
  • Hi, Scott

    I test with what you said, which makes the DataGridView fill to dock on the form, resize the form, but no vertical lines appear.

    • Proposed as answer by Youngsun Noh Wednesday, October 23, 2013 4:38 AM
    Monday, January 7, 2008 3:19 AM
  • can u help in doing for a particular header like below

     

     

    Date Name/Bill Number Due Date (or) Credit Days Amount
      | | | |
      | | | |
      | | | |
      | | | |
      | | | |
      | | | |
      | | | |

     

     

     

     

    Thanks in advance

     

    Wednesday, January 9, 2008 2:35 PM
  • Thanks for that !
    I was hunting for the same from last few days Smile
    Monday, March 24, 2008 5:43 AM
  • can this merging also be done vertically? for example, rows 3 and 4 for column 1 will be merged as 1. will it display a single value?
    Thursday, September 4, 2008 4:26 AM
  • Raj - Here is the VB NET 3.5 version :   To run the code: Create a new FORM with a blank Datagridview in it , then enter the following code behind it (the code will display a datagridview with two headers. The top header will represent headings with TWO columns MERGED for each heading, second header will show single column headings ):



    Public Class Form1

        Private Sub DataGridView1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


            Me.DataGridView1.Columns.Add("JanWin", "Win")
            Me.DataGridView1.Columns.Add("JanLoss", "Loss")
            Me.DataGridView1.Columns.Add("FebWin", "Win")
            Me.DataGridView1.Columns.Add("FebLoss", "Loss")
            Me.DataGridView1.Columns.Add("MarWin", "Win")
            Me.DataGridView1.Columns.Add("MarLoss", "Loss")
            Me.DataGridView1.Columns.Add("AprWin", "Win")
            Me.DataGridView1.Columns.Add("AprLoss", "Loss")
            Me.DataGridView1.Columns.Add("MayWin", "Win")
            Me.DataGridView1.Columns.Add("MayLoss", "Loss")

            For j As Integer = 0 To Me.DataGridView1.ColumnCount - 1
                Me.DataGridView1.Columns(j).Width = 45
            Next

            Me.DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
            Me.DataGridView1.ColumnHeadersHeight = Me.DataGridView1.ColumnHeadersHeight * 2
            Me.DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter
            AddHandler Me.DataGridView1.CellPainting, AddressOf dataGridView1_CellPainting
            AddHandler Me.DataGridView1.Paint, AddressOf dataGridView1_Paint
            AddHandler Me.DataGridView1.Scroll, AddressOf dataGridView1_Scroll
            AddHandler Me.DataGridView1.ColumnWidthChanged, AddressOf dataGridView1_ColumnWidthChanged
        End Sub



        Private Sub dataGridView1_ColumnWidthChanged(ByVal sender As Object, ByVal e As DataGridViewColumnEventArgs)
            Dim rtHeader As Rectangle = Me.DataGridView1.DisplayRectangle
            rtHeader.Height = Me.DataGridView1.ColumnHeadersHeight / 2
            Me.DataGridView1.Invalidate(rtHeader)
        End Sub



        Private Sub dataGridView1_Scroll(ByVal sender As Object, ByVal e As ScrollEventArgs)

            Dim rtHeader As Rectangle = Me.DataGridView1.DisplayRectangle
            rtHeader.Height = Me.DataGridView1.ColumnHeadersHeight / 2
            Me.DataGridView1.Invalidate(rtHeader)
        End Sub



        Private Sub dataGridView1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs)
            Dim monthes As String() = {"January", "February", "March", "April", "May"}
            Dim j As Integer = 0
            While j < 10
                Dim r1 As Rectangle = Me.DataGridView1.GetCellDisplayRectangle(j, -1, True)
                Dim w2 As Integer = Me.DataGridView1.GetCellDisplayRectangle(j + 1, -1, True).Width
                r1.X += 1
                r1.Y += 1
                r1.Width = r1.Width + w2 - 2
                r1.Height = r1.Height / 2 - 2
                e.Graphics.FillRectangle(New SolidBrush(Me.DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1)
                Dim format As New StringFormat()
                format.Alignment = StringAlignment.Center
                format.LineAlignment = StringAlignment.Center
                e.Graphics.DrawString(monthes(j / 2), Me.DataGridView1.ColumnHeadersDefaultCellStyle.Font, New SolidBrush(Me.DataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format)
                j += 2
            End While
        End Sub



        Private Sub dataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs)

            If e.RowIndex = -1 AndAlso e.ColumnIndex > -1 Then
                Dim r2 As Rectangle = e.CellBounds
                r2.Y += e.CellBounds.Height / 2
                r2.Height = e.CellBounds.Height / 2
                e.PaintBackground(r2, True)
                e.PaintContent(r2)
                e.Handled = True
            End If
        End Sub

    End Class

    • Proposed as answer by Rockeyey Wednesday, February 8, 2012 11:24 AM
    Sunday, March 14, 2010 6:17 PM
  • In continuation to the above question, Any idea

    1. How can we manage the highlight line around merged header cells to span completely and

    2. Handling the Column reorder (When any other column is dragged and dropped in between the merged columns)

    Thursday, November 25, 2010 6:55 PM
  • thanks brother

    jesus loves you :)

    • Proposed as answer by KSHONG Sunday, June 17, 2018 1:54 AM
    Tuesday, April 10, 2012 3:53 AM
  • hi Zhi-Xin Ye

    Your codes are working fine. But there is 1 problem that when i scroll in datagrid headers are also scrolling with scrollbar. for example

    1         2          3           4           5          6

    at present 1,2,3 are visible columns. when i scroll in datagrid header are scrolling and showing 1,2,3 only instead of 4,5,6.

    Thursday, April 12, 2012 10:30 AM