In this article I will explain with an example, how to merge multiple Header Columns (Cells) in DataGridView in Windows Forms (WinForms) application using C# and VB.Net.
There is no direct way to merge multiple Header Columns (Cells) in DataGridView and hence this article will illustrate how to achieve the same by drawing a Rectangle over the existing Header Columns (Cells) in DataGridView using C# and VB.Net.
 
 
Form Design
The Form consists of a DataGridView control. The DataGridView has been assigned a Paint event handler.
Merge multiple Header Columns (Cells) in DataGridView using C# and VB.Net
 
 
Populating the DataGridView
Inside the Form Load event handler, the DataGridView is populated with data by making use of a dynamic DataTable with some records.
C#
private void Form1_Load(object sender, EventArgs e)
{
    DataTable dt = new DataTable();
    dt.Columns.AddRange(new DataColumn[4] { new DataColumn("Id", typeof(int)),
    new DataColumn("Name", typeof(string)),
    new DataColumn("City", typeof(string)),
    new DataColumn("Country",typeof(string)) });
    dt.Rows.Add(1, "John Hammond", "Chicago", "United States");
    dt.Rows.Add(2, "Mudassar Khan", "Mumbai", "India");
    dt.Rows.Add(3, "Suzanne Mathews", "Paris", "France");
    dt.Rows.Add(4, "Robert Schidner", "Moscow", "Russia");
    this.dataGridView1.DataSource = dt;
}
 
VB.Net
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim dt As DataTable = New DataTable()
    dt.Columns.AddRange(New DataColumn(3) {New DataColumn("Id", GetType(Integer)), New DataColumn("Name", GetType(String)), New DataColumn("City", GetType(String)), New DataColumn("Country", GetType(String))})
    dt.Rows.Add(1, "John Hammond", "Chicago", "United States")
    dt.Rows.Add(2, "Mudassar Khan", "Mumbai", "India")
    dt.Rows.Add(3, "Suzanne Mathews", "Paris", "France")
    dt.Rows.Add(4, "Robert Schidner", "Moscow", "Russia")
    Me.dataGridView1.DataSource = dt
End Sub
 
 
Merging multiple Header Columns (Cells) in DataGridView
Inside the Paint event handler, first the coordinates i.e. X and Y position and the width of the Header Columns (Cells) to be merged is determined using the GetCellDisplayRectangle function of the DataGridView.
Then a Rectangle is drawn over the Header Columns (Cells) to be merged using the coordinates and dimensions determined earlier.
Finally, the Text is drawn over the Rectangle.
C#
private void dataGridView1_Paint(object sender, PaintEventArgs e)
{
    //Offsets to adjust the position of the merged Header.
    int heightOffset = -5;
    int widthOffset = -2;
    int xOffset = 0;
    int yOffset = 4;
 
    //Index of Header column from where the merging will start.
    int columnIndex = 2;
 
    //Number of Header columns to be merged.
    int columnCount = 2;
 
    //Get the position of the Header Cell.
    Rectangle headerCellRectangle = dataGridView1.GetCellDisplayRectangle(columnIndex, 0, true);
 
    //X coordinate of the merged Header Column.
    int xCord = headerCellRectangle.Location.X + xOffset;
 
    //Y coordinate of the merged Header Column.
    int yCord = headerCellRectangle.Location.Y - headerCellRectangle.Height + yOffset;
 
    //Calculate Width of merged Header Column by adding the widths of all Columns to be merged.
    int mergedHeaderWidth = dataGridView1.Columns[columnIndex].Width + dataGridView1.Columns[columnIndex + columnCount - 1].Width + widthOffset;
           
    //Generate the merged Header Column Rectangle.
    Rectangle mergedHeaderRect = new Rectangle(xCord, yCord, mergedHeaderWidth, headerCellRectangle.Height + heightOffset);
 
    //Draw the merged Header Column Rectangle.
    e.Graphics.FillRectangle(new SolidBrush(Color.White), mergedHeaderRect);
 
    //Draw the merged Header Column Text.
    e.Graphics.DrawString("Address", dataGridView1.ColumnHeadersDefaultCellStyle.Font, Brushes.Black, xCord + 2, yCord + 3);
}
 
VB.Net
Private Sub dataGridView1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles dataGridView1.Paint
    'Offsets to adjust the position of the merged Header.
    Dim heightOffset As Integer = -5
    Dim widthOffset As Integer = -2
    Dim xOffset As Integer = 0
    Dim yOffset As Integer = 4
 
    'Index of Header column from where the merging will start.
    Dim columnIndex As Integer = 2
 
    'Number of Header columns to be merged.
    Dim columnCount As Integer = 2
 
    'Get the position of the Header Cell.
    Dim headerCellRectangle As Rectangle = dataGridView1.GetCellDisplayRectangle(columnIndex, 0, True)
 
    'X coordinate of the merged Header Column.
    Dim xCord As Integer = (headerCellRectangle.Location.X + xOffset)
 
    'Y coordinate of the merged Header Column.
    Dim yCord As Integer = ((headerCellRectangle.Location.Y - headerCellRectangle.Height) + yOffset)
 
    'Calculate Width of merged Header Column by adding the widths of all Columns to be merged.
    Dim mergedHeaderWidth As Integer = (dataGridView1.Columns(columnIndex).Width + (dataGridView1.Columns((columnIndex + (columnCount - 1))).Width + widthOffset))
 
    'Generate the merged Header Column Rectangle.
    Dim mergedHeaderRect As Rectangle = New Rectangle(xCord, yCord, mergedHeaderWidth, (headerCellRectangle.Height + heightOffset))
 
    'Draw the merged Header Column Rectangle.
    e.Graphics.FillRectangle(New SolidBrush(Color.White), mergedHeaderRect)
 
    'Draw the merged Header Column Text.
    e.Graphics.DrawString("Address", dataGridView1.ColumnHeadersDefaultCellStyle.Font, Brushes.Black, (xCord + 2), (yCord + 3))
End Sub
 
 
Screenshots
DataGridView without Merged Header Columns (Cells)
Merge multiple Header Columns (Cells) in DataGridView using C# and VB.Net
 
DataGridView with Merged Header Columns (Cells)
Merge multiple Header Columns (Cells) in DataGridView using C# and VB.Net
 
 
Downloads