locked
Multi-line (merged) datagridview header RRS feed

  • Question

  • Hi All,

    How can I have a multi-line header with the top header row merged?  (see illustration below)
    -------------------------------------------------
          |   January   |   February  |     March   |
          |  Win | Loss |  Win | Loss |  Win | Loss |
    -------------------------------------------------
    Team1 |      |      |      |      |      |      |
    Team2 |      |      |      |      |      |      |
    TeamN |      |      |      |      |      |      |
    -------------------------------------------------

    Any help will be very much appreciated.

    TIA!
    Wednesday, March 21, 2007 2:39 PM

Answers

  • For just merging the headercell, look at my sample:

    namespace Sample4

    {

        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");

     

                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);

     

            }

     

            void dataGridView1_Paint(object sender, PaintEventArgs e)

            {

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

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

                {

                    Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true); //get the column header cell

                    r1.X += 1;

                    r1.Y += 1;

                    r1.Width = r1.Width * 2 - 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)

                {

                    e.PaintBackground(e.CellBounds, false);

                   

                    Rectangle r2 = e.CellBounds;

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

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

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

        }

    }

    Thursday, March 22, 2007 6:52 AM

All replies

  • You have to custom draw the datagridview, what's the structure of your datatable?
    Thursday, March 22, 2007 5:59 AM
  • For just merging the headercell, look at my sample:

    namespace Sample4

    {

        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");

     

                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);

     

            }

     

            void dataGridView1_Paint(object sender, PaintEventArgs e)

            {

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

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

                {

                    Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true); //get the column header cell

                    r1.X += 1;

                    r1.Y += 1;

                    r1.Width = r1.Width * 2 - 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)

                {

                    e.PaintBackground(e.CellBounds, false);

                   

                    Rectangle r2 = e.CellBounds;

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

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

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

        }

    }

    Thursday, March 22, 2007 6:52 AM
  • thanks very much! i'm still working on the Sort symbol being vertically aligned thus being cut on some instance.
    Friday, March 30, 2007 7:16 AM
  • Could you put that code in VB language please. I have a problem when i try to call the event =(
    Wednesday, November 18, 2009 4:36 PM
  • Here's the VB version.  I also added the "Team" column (column 0)

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

            With dataGridView1
                .Columns.Add("Team", "Team")
                .Columns.Add("JanWin", "Win")
                .Columns.Add("JanLoss", "Loss")
                .Columns.Add("FebWin", "Win")
                .Columns.Add("FebLoss", "Loss")
                .Columns.Add("MarWin", "Win")
                .Columns.Add("MarLoss", "Loss")

                ' Schedule column widths
                For j As Integer = 1 To .Columns.Count - 1
                    .Columns(j).Width = 45
                Next

                .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
                .ColumnHeadersHeight = .ColumnHeadersHeight * 2
                .ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter

            End With

        End Sub

        Private Sub dataGridView1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles dataGridView1.Paint

            Dim days As String() = {"January", "February", "March"}
            Dim r1 As Rectangle
            Dim format As StringFormat

            ' Fill-in the empty space above the column 0 header
            r1 = dataGridView1.GetCellDisplayRectangle(0, -1, True)
            r1.X += 1
            r1.Y += 1
            r1.Width = r1.Width * 2 - 2
            r1.Height = r1.Height / 2 - 1
            e.Graphics.FillRectangle(New SolidBrush(Me.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1)
            format = New StringFormat()
            format.Alignment = StringAlignment.Center
            format.LineAlignment = StringAlignment.Center

            For j As Integer = 0 To 6 Step 2
                r1 = dataGridView1.GetCellDisplayRectangle(j + 1, -1, True)
                r1.X += 1
                r1.Y += 1
                r1.Width = r1.Width * 2 - 2
                r1.Height = r1.Height / 2 - 1
                e.Graphics.FillRectangle(New SolidBrush(Me.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1)
                format = New StringFormat()
                format.Alignment = StringAlignment.Center
                format.LineAlignment = StringAlignment.Center
                e.Graphics.DrawString(days(j / 2), _
                                      dataGridView1.ColumnHeadersDefaultCellStyle.Font, _
                                      New SolidBrush(Me.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format)
            Next

        End Sub

        Private Sub dataGridView1_CellPainting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dataGridView1.CellPainting

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

        End Sub

    Friday, November 20, 2009 9:40 PM
  • Hi,

     

    I am also having the same requirement of displaying the multi level merged datagridview header cells. I have tried to use your code, its working fine except a few issues like:

    1. While I resize the columns through mouse, the Top level header does not resizes itself and a lot of flickering on the column headers.

    2. Also the top level header does not changes its back color or theme on mouse over.

     

    Could you please suggest me the modifications required in the above code example which you provided as the answer to the post? It will be a great help.

     

    Thanks

    Regards,

    Dhirendra

     

     

    Friday, July 30, 2010 2:25 PM
  • Your coding is very good. I am writing a personal budget application. How do I get the columns "January" "February" and "March" to span over three columns instead of two. Like this:

    I looked at the Paint and CellPainting event, but I am not sure on, which line to edit or how to edit it to get the above result.

    Regards

    marvil


    marvil

    Thursday, May 24, 2012 10:11 PM
  • Hi Leon, have you managed to vertically relocate the sort glyph?

    Any clue will be appreciated!

    Wednesday, July 11, 2012 7:49 PM
  • Hi,

    For Quarterly.

    private void btnReport_Click(object sender, EventArgs e)

    {

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

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

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

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

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

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

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

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

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

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

                this.dgvPlannedProfile.Columns.Add("JuneWin", "Win");

                this.dgvPlannedProfile.Columns.Add("JuneLoss", "Loss");

                this.dgvPlannedProfile.Columns.Add("JulyWin", "Win");

                this.dgvPlannedProfile.Columns.Add("JulyLoss", "Loss");

                this.dgvPlannedProfile.Columns.Add("AugWin", "Win");

                this.dgvPlannedProfile.Columns.Add("AugLoss", "Loss");

                this.dgvPlannedProfile.Columns.Add("SepWin", "Win");

                this.dgvPlannedProfile.Columns.Add("SepLoss", "Loss");
                this.dgvPlannedProfile.Columns.Add("OctWin", "Win");

                this.dgvPlannedProfile.Columns.Add("OctLoss", "Loss");

                this.dgvPlannedProfile.Columns.Add("NovWin", "Win");

                this.dgvPlannedProfile.Columns.Add("NovLoss", "Loss");

                this.dgvPlannedProfile.Columns.Add("DecWin", "Win");

                this.dgvPlannedProfile.Columns.Add("DecLoss", "Loss");



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

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

                }

                this.dgvPlannedProfile.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;

                this.dgvPlannedProfile.ColumnHeadersHeight = this.dgvPlannedProfile.ColumnHeadersHeight * 3;

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

                this.dgvPlannedProfile.CellPainting += new DataGridViewCellPaintingEventHandler(dgvPlannedProfile_CellPainting);

                this.dgvPlannedProfile.Paint += new PaintEventHandler(dgvPlannedProfile_Paint);
            }

            void dgvPlannedProfile_Paint(object sender, PaintEventArgs e)
            {
                string[] quarter = { "1st", "2nd", "3rd", "4th" };
                string[] monthes = { "January", "February", "March","April","May","June","July","August","September","October","NovemBer","December" };

                for (int k = 0; k < 24; )
                {

                    Rectangle rtop = this.dgvPlannedProfile.GetCellDisplayRectangle(k, -1, true); //get the column header cell

                    rtop.X += 1;

                    rtop.Y += 1;
                    rtop.Width = rtop.Width * 6 - 2;

                    rtop.Height = System.Convert.ToInt32(rtop.Height / 3) - 2;

                    e.Graphics.FillRectangle(new SolidBrush(this.dgvPlannedProfile.ColumnHeadersDefaultCellStyle.BackColor), rtop);

                    StringFormat formattop = new StringFormat();

                    formattop.Alignment = StringAlignment.Center;

                    formattop.LineAlignment = StringAlignment.Center;

                    e.Graphics.DrawString(quarter[k / 6],

                        this.dgvPlannedProfile.ColumnHeadersDefaultCellStyle.Font,

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

                        rtop,

                        formattop);
                    k += 6;
                }

                for (int j = 0; j < 24; )
                {

                    Rectangle r1 = this.dgvPlannedProfile.GetCellDisplayRectangle(j, -1, true); //get the column header cell

                    r1.X += 1;

                    r1.Y += 1 + 15;

                    r1.Width = r1.Width * 2 - 2;

                    r1.Height = System.Convert.ToInt32(r1.Height / 3) - 2;

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

                    StringFormat format = new StringFormat();

                    format.Alignment = StringAlignment.Center;

                    format.LineAlignment = StringAlignment.Center;

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

                        this.dgvPlannedProfile.ColumnHeadersDefaultCellStyle.Font,

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

                        r1,

                        format);


                    j += 2;

                }

            }
            void dgvPlannedProfile_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
            {

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

                    e.PaintBackground(e.CellBounds, false);



                    Rectangle r2 = e.CellBounds;

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

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

                    e.PaintContent(r2);

                    e.Handled = true;

                }

            }

    Monday, August 20, 2012 11:14 AM
  • Your code is awesome!! I want to add an additional line to top of them. How can I do this?? I am now using your code. Thanks in advance...
    Friday, December 30, 2016 3:28 PM