locked
How can i merge two Cells Of Datagridview control in VB.net.

    Question

  • Hello Everybody,

    I am a vb 6.0 Developer and now turn into vb.net.

    i study the datagridview control. i insert the value in all cells successfully at run-time which i want.

    But now My Major Problem is that i want to Merge Two Cells of DataGridView Control.

    i m not having any idea of that one.

    Is it possible?.

    If yes then plz reply me with code or if there is a property of merging two  cell  then also respond me.

    Thanks a lot....

    Dharmchand Dhingra.......
     


    Thursday, March 27, 2008 1:13 PM

Answers

  • Hi Dharmchand,

    Windows Forms DataGridView control has no related properties or methods to merge cells. But you can use Graphics.DrawLine and Graphics.DrawString methods to draw the effect in DataGridView.CellPainting event.

    1 Code sample: Vertically merge cells in DataGridView

    Imports System.Data.OleDb  
     
    Public Class Form1  
     
        Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load  
            Dim con As OleDbConnection = New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=D:\myDB.mdb")  
            Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM Users", con)  
            con.Open()  
            Dim myDA As OleDbDataAdapter = New OleDbDataAdapter(cmd)  
            Dim myDataSet As DataSet = New DataSet()  
            myDA.Fill(myDataSet, "MyTable")  
            DataGridView1.DataSource = myDataSet.Tables("MyTable").DefaultView  
            con.Close()  
            con = Nothing 
        End Sub 
     
        'e.g. Vertically merge the same cells of the fourth column  
        Private Sub DataGridView1_CellPainting(ByVal sender As System.ObjectByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting  
     
            If e.ColumnIndex = 3 AndAlso e.RowIndex <> -1 Then 
     
                Using gridBrush As Brush = New SolidBrush(Me.DataGridView1.GridColor), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)  
     
                    Using gridLinePen As Pen = New Pen(gridBrush)  
                        ' Clear cell  
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds)  
     
                        ' Draw line (bottom border and right border of current cell)  
                        'If next row cell has different content, only draw bottom border line of current cell  
                        If e.RowIndex < DataGridView1.Rows.Count - 2 AndAlso DataGridView1.Rows(e.RowIndex + 1).Cells(e.ColumnIndex).Value.ToString() <> e.Value.ToString() Then 
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)  
                        End If 
     
                        ' Draw right border line of current cell  
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)  
     
                        ' draw/fill content in current cell, and fill only one cell of multiple same cells  
                        If Not e.Value Is Nothing Then 
                            If e.RowIndex > 0 AndAlso DataGridView1.Rows(e.RowIndex - 1).Cells(e.ColumnIndex).Value.ToString() = e.Value.ToString() Then 
                            Else 
                                e.Graphics.DrawString(CType(e.Value, String), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + 5, StringFormat.GenericDefault)  
                            End If 
                        End If 
     
                        e.Handled = True 
                    End Using  
                End Using  
            End If 
        End Sub 
     
    End Class 

    Illustration:


    2 Cose sample: Horizontally merge cells in DataGridView
    Another sample:
    http://www.codeguru.com/forum/showthread.php?p=1537635#post1537635

    It provides a demo project: DataGridView_MergeDemo.zip

    Here are two helpful tools:
    1. Instant VB: C# to VB converter

    The tool can convert entire C# project to corresponding VB.NET project, also can convert code snippet.
    2. Convert C# code to VB.NET code by means of this Code Translator tool.

    Best regards,
    Martin Xie

    Monday, March 31, 2008 6:44 AM

All replies

  • Hi Dharmchand,

    Windows Forms DataGridView control has no related properties or methods to merge cells. But you can use Graphics.DrawLine and Graphics.DrawString methods to draw the effect in DataGridView.CellPainting event.

    1 Code sample: Vertically merge cells in DataGridView

    Imports System.Data.OleDb  
     
    Public Class Form1  
     
        Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load  
            Dim con As OleDbConnection = New OleDbConnection("Provider=Microsoft.jet.oledb.4.0;data source=D:\myDB.mdb")  
            Dim cmd As OleDbCommand = New OleDbCommand("SELECT * FROM Users", con)  
            con.Open()  
            Dim myDA As OleDbDataAdapter = New OleDbDataAdapter(cmd)  
            Dim myDataSet As DataSet = New DataSet()  
            myDA.Fill(myDataSet, "MyTable")  
            DataGridView1.DataSource = myDataSet.Tables("MyTable").DefaultView  
            con.Close()  
            con = Nothing 
        End Sub 
     
        'e.g. Vertically merge the same cells of the fourth column  
        Private Sub DataGridView1_CellPainting(ByVal sender As System.ObjectByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting  
     
            If e.ColumnIndex = 3 AndAlso e.RowIndex <> -1 Then 
     
                Using gridBrush As Brush = New SolidBrush(Me.DataGridView1.GridColor), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)  
     
                    Using gridLinePen As Pen = New Pen(gridBrush)  
                        ' Clear cell  
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds)  
     
                        ' Draw line (bottom border and right border of current cell)  
                        'If next row cell has different content, only draw bottom border line of current cell  
                        If e.RowIndex < DataGridView1.Rows.Count - 2 AndAlso DataGridView1.Rows(e.RowIndex + 1).Cells(e.ColumnIndex).Value.ToString() <> e.Value.ToString() Then 
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)  
                        End If 
     
                        ' Draw right border line of current cell  
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)  
     
                        ' draw/fill content in current cell, and fill only one cell of multiple same cells  
                        If Not e.Value Is Nothing Then 
                            If e.RowIndex > 0 AndAlso DataGridView1.Rows(e.RowIndex - 1).Cells(e.ColumnIndex).Value.ToString() = e.Value.ToString() Then 
                            Else 
                                e.Graphics.DrawString(CType(e.Value, String), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + 5, StringFormat.GenericDefault)  
                            End If 
                        End If 
     
                        e.Handled = True 
                    End Using  
                End Using  
            End If 
        End Sub 
     
    End Class 

    Illustration:


    2 Cose sample: Horizontally merge cells in DataGridView
    Another sample:
    http://www.codeguru.com/forum/showthread.php?p=1537635#post1537635

    It provides a demo project: DataGridView_MergeDemo.zip

    Here are two helpful tools:
    1. Instant VB: C# to VB converter

    The tool can convert entire C# project to corresponding VB.NET project, also can convert code snippet.
    2. Convert C# code to VB.NET code by means of this Code Translator tool.

    Best regards,
    Martin Xie

    Monday, March 31, 2008 6:44 AM
  • can this be done vertically? like this:

    • Edited by mmel_g Thursday, September 04, 2008 4:31 AM add image link
    • Edited by Martin Xie - MSFT Friday, September 05, 2008 3:58 AM Edit HTML view code to display screenshot in your post.
    Thursday, September 04, 2008 4:03 AM
  • Hi mmel_g,

    Actually, that code sample in my previous post demonstrates how to v
    ertically merge cells in DataGridView.

    I have modified my post. Please check it.


    Best regards,
    Martin Xie

    Friday, September 05, 2008 6:11 AM
  • good post. 

    The example worked great except I need to  be able to select one of the merged items.  is there any way to do that?
    Wednesday, April 15, 2009 4:08 AM
  • Hiii,

    Can u please provide datagridview horizontal mergecell vb.net code,

    Regards,
    Firoz.
    Saturday, June 20, 2009 10:37 PM
  • Excellent code thanks.
    I think there's a minor bug in the line drawing, e.RowIndex < DataGridView1.Rows.Count - 2 should be . . .-1
    otherwise the line isn't drawn if they are the bottom two rows in the grid.
    Any insights into selecting 'through' the merged cells to the underlying rows would be welcomed here too.

    So far I've added this code:

      If dgResults.Rows(e.RowIndex).Selected Then
                    ourbackcolor = e.CellStyle.SelectionBackColor
                Else
                    ourbackcolor = e.CellStyle.BackColor
                End If

                Using gridBrush As Brush = New SolidBrush(Me.dgResults.GridColor), backColorBrush As Brush = New SolidBrush(ourbackcolor) . . ..


    This will display the highlight across the row - not 100% ideal, but IMHO better than nothing.


    pg

    • Edited by pg53 Wednesday, December 02, 2009 1:26 PM code added
    Wednesday, December 02, 2009 2:55 AM
  • Hi
         Good code snipet
    If e.RowIndex < DataGridView1.Rows.Count - 2 AndAlso DataGridView1.Rows(e.RowIndex + 1).Cells(e.ColumnIndex).Value.ToString() <> e.Value.ToString() Then
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)

    End If

    it show the nullReference Exception in e.value it has nothing how to fix this

    and one more doubt

    i want to merge row wise also and in the merged cell i want to place a checkbox

    please give me a code
    Wednesday, January 06, 2010 6:48 AM
  • Suppose one want to merge Cell 2 and 3 in Row 0 of a Datagrid(dg_ESC) then type following code in Cell Painting event of the Datagrid

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


    If e.RowIndex = 0 AndAlso (e.ColumnIndex = 2 Or e.ColumnIndex = 3) Then

    Using gridBrush As Brush = New SolidBrush(Me.dg_ESC.GridColor), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)

    Using gridLinePen As Pen = New Pen(gridBrush)

    ' Clear cell

    e.Graphics.FillRectangle(backColorBrush, e.CellBounds)

    'Bottom line drawing

    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)

    'top line drawing

    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Top)

    'Drawing Right line

    If e.ColumnIndex = 3 Then

    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)

    End If

    'Inserting text

    If e.ColumnIndex = 3 Then

    e.Graphics.DrawString(CType(e.Value, String), e.CellStyle.Font, Brushes.Black, e.CellBounds.X - (e.CellBounds.X / 4), e.CellBounds.Y + 5)

    End If

    e.Handled = True

    End Using

    End Using

    End If

    This solve's the problem...

    Thanking

    Rakesh Sharma,

    Jodhpur INDIA

    Thursday, January 20, 2011 7:39 AM
  • Hi to all,

    This is for merge two columns ,but if you want row wise plz put rowindex in columnindex place., This is working ., thanks to all


    Using gridBrush As Brush = New SolidBrush(Color.Black), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)
                    Using gridLinePen As Pen = New Pen(gridBrush)
                        ' Clear cell  
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds)

                        ' Draw line (bottom border and right border of current cell)  
                        'If next row cell has different content, only draw bottom border line of current cell  
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1)
                        If e.ColumnIndex < gridPreFinal2.Columns.Count - 1 AndAlso gridPreFinal2.Columns(e.ColumnIndex + 1).HeaderText.ToString() <> gridPreFinal2.Columns(e.ColumnIndex).HeaderText.ToString() Then
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)
                        End If

                        ' Draw right border line of current cell  
                        'e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)


                        'cURRENT_cELL_vALUE = gridPreFinal2.Columns(e.ColumnIndex).HeaderText



                        Dim recdest As RectangleF = RectangleF.Empty
                        Dim sf As New StringFormat
                        sf.Alignment = StringAlignment.Center
                        sf.LineAlignment = StringAlignment.Center
                        sf.Trimming = StringTrimming.EllipsisCharacter
                        'sf.

                        Dim WIDTH_S As Integer

                        WIDTH_S = 183 + 50

                        recdest = New RectangleF(e.CellBounds.Left - (WIDTH_S + WIDTH_S + WIDTH_S), e.CellBounds.Top, WIDTH_S + WIDTH_S, e.CellBounds.Height)
                        ' draw/fill content in current cell, and fill only one cell of multiple same cells  
                        If Not e.Value Is Nothing Then
                            If e.ColumnIndex = 0 Then
                                nulstring = e.Value.ToString
                                e.CellStyle.BackColor = Color.Orange
                                recdest = New RectangleF(e.CellBounds.Left, e.CellBounds.Top, 100, 40)
                                e.Graphics.DrawString(nulstring, e.CellStyle.Font, Brushes.White, recdest, sf)
                            Else
                                If e.RowIndex = -1 AndAlso gridPreFinal2.Columns(e.ColumnIndex - 1).HeaderText.ToString() = gridPreFinal2.Columns(e.ColumnIndex).HeaderText.ToString() Then

                                Else
                                    nulstring = e.Value.ToString
                                    e.CellStyle.BackColor = Color.Orange
                                    recdest = New RectangleF(e.CellBounds.Left, e.CellBounds.Top, 100, 40)
                                    e.Graphics.DrawString(nulstring, e.CellStyle.Font, Brushes.White, recdest, sf)

                                End If
                            End If

                        End If

                        e.Handled = True
                    End Using
                End Using

    Saturday, January 22, 2011 5:20 PM
  • Using gridBrush As Brush = New SolidBrush(Color.Black), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)
                    Using gridLinePen As Pen = New Pen(gridBrush)
                        ' Clear cell  
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds)

                        ' Draw line (bottom border and right border of current cell)  
                        'If next row cell has different content, only draw bottom border line of current cell  
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1)
                        If e.ColumnIndex < gridPreFinal2.Columns.Count - 1 AndAlso gridPreFinal2.Columns(e.ColumnIndex + 1).HeaderText.ToString() <> gridPreFinal2.Columns(e.ColumnIndex).HeaderText.ToString() Then
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)
                        End If

                        ' Draw right border line of current cell  
                        'e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)


                        'cURRENT_cELL_vALUE = gridPreFinal2.Columns(e.ColumnIndex).HeaderText



                        Dim recdest As RectangleF = RectangleF.Empty
                        Dim sf As New StringFormat
                        sf.Alignment = StringAlignment.Center
                        sf.LineAlignment = StringAlignment.Center
                        sf.Trimming = StringTrimming.EllipsisCharacter
                        'sf.

                        Dim WIDTH_S As Integer

                        WIDTH_S = 183 + 50

                        recdest = New RectangleF(e.CellBounds.Left - (WIDTH_S + WIDTH_S + WIDTH_S), e.CellBounds.Top, WIDTH_S + WIDTH_S, e.CellBounds.Height)
                        ' draw/fill content in current cell, and fill only one cell of multiple same cells  
                        If Not e.Value Is Nothing Then
                            If e.ColumnIndex = 0 Then
                                nulstring = e.Value.ToString
                                e.CellStyle.BackColor = Color.Orange
                                recdest = New RectangleF(e.CellBounds.Left, e.CellBounds.Top, 100, 40)
                                e.Graphics.DrawString(nulstring, e.CellStyle.Font, Brushes.White, recdest, sf)
                            Else
                                If e.RowIndex = -1 AndAlso gridPreFinal2.Columns(e.ColumnIndex - 1).HeaderText.ToString() = gridPreFinal2.Columns(e.ColumnIndex).HeaderText.ToString() Then

                                Else
                                    nulstring = e.Value.ToString
                                    e.CellStyle.BackColor = Color.Orange
                                    recdest = New RectangleF(e.CellBounds.Left, e.CellBounds.Top, 100, 40)
                                    e.Graphics.DrawString(nulstring, e.CellStyle.Font, Brushes.White, recdest, sf)

                                End If
                            End If

                        End If

                        e.Handled = True
                    End Using
                End Using

    Thanks
    Mathan
    tamilNadu

    Saturday, January 22, 2011 5:27 PM
  • The best solution will be:
    
                    Using gridBrush As Brush = New SolidBrush(Me.DataGridView1.GridColor), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)
    
                        Using gridLinePen As Pen = New Pen(gridBrush)
                            ' Clear cell   
                            e.Graphics.FillRectangle(backColorBrush, e.CellBounds)
    
                            ' Draw line (bottom border and right border of current cell)   
                            'If next row cell has different content, only draw bottom border line of current cell   
                            If e.RowIndex < DataGridView1.Rows.Count - 1 AndAlso DataGridView1.Rows(e.RowIndex + 1).Cells(e.ColumnIndex).Value.ToString() <> e.Value.ToString() Then
                                e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)
                            End If
    
                            ' Draw right border line of current cell   
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)
    
                            ' draw/fill content in current cell, and fill only one cell of multiple same cells   
                            If Not e.Value Is Nothing Then
                                Dim previos As Integer = 0
                                Dim siguientes As Integer = 0
                                For i As Integer = e.RowIndex - 1 To 0 Step -1
                                    If DataGridView1.Item(e.ColumnIndex, i).Value <> e.Value Or i = 0 Then
                                        previos = e.RowIndex - i - 1
                                        Exit For
                                    End If
                                Next
                                For i As Integer = e.RowIndex + 1 To DataGridView1.Rows.Count - 1
                                    If DataGridView1.Item(e.ColumnIndex, i).Value <> e.Value Or DataGridView1.Rows.Count - 1 = i Then
                                        siguientes = i - e.RowIndex - 1
                                        Exit For
                                    End If
                                Next
    
                                If siguientes = previos Or siguientes - 1 = previos Then
                                    e.Graphics.DrawString(CType(e.Value, String), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + 3, StringFormat.GenericDefault)
                                End If
                                'End If
                            End If
    
                            e.Handled = True
                        End Using
                    End Using
    

     

    This puts the value near to the middle of the merged cells

    Tuesday, September 20, 2011 5:26 PM
  • your solution seems very good. now I want to use your code in a sub and call it. What I want to do is to transfer dgv, e, RowIndex (say 1 to 2) and  ColumnIndex (say 3 to 4) to call the sub. I don't know how to modify 

                      e.Graphics.FillRectangle(backColorBrush, e.CellBounds)
    
    Thank you.

    Thursday, October 06, 2011 9:00 PM
  • I use this code: 

        Private Sub DataGridView1_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
            If DataGridView1.Columns(e.ColumnIndex).Tag = "M" AndAlso e.RowIndex <> -1 Then
                Using gridBrush As Brush = New SolidBrush(Me.DataGridView1.GridColor), backColorBrush As Brush = New SolidBrush(e.CellStyle.BackColor)
    
                    Using gridLinePen As Pen = New Pen(gridBrush)
                        ' Clear cell   
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds)
    
                        ' Draw line (bottom border and right border of current cell)   
                        'If next row cell has different content, only draw bottom border line of current cell   
                        If e.RowIndex = DataGridView1.Rows.Count - 1 OrElse DataGridView1.Item(e.ColumnIndex, e.RowIndex + 1).Value.ToString() <> e.Value.ToString() Then
                            e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1)
                        End If
    
                        ' Draw right border line of current cell   
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom)
    
                        ' draw/fill content in current cell, and fill only one cell of multiple same cells   
                        If Not e.Value Is Nothing Then
                            'If e.RowIndex > 0 AndAlso DataGridView1.Rows(e.RowIndex - 1).Cells(e.ColumnIndex).Value.ToString() = e.Value.ToString() Then
                            'Else
    
    
                            Dim previos As Integer = 0
                            Dim siguientes As Integer = 0
                            For i As Integer = e.RowIndex - 1 To 0 Step -1
                                If DataGridView1.Item(e.ColumnIndex, i).Value <> e.Value Or i = 0 Or DataGridView1.Item(e.ColumnIndex, i).Displayed = False Then
                                    previos = e.RowIndex - i - 1
                                    Exit For
                                End If
                            Next
                            For i As Integer = e.RowIndex + 1 To DataGridView1.Rows.Count - 1
                                If DataGridView1.Item(e.ColumnIndex, i).Value <> e.Value Or DataGridView1.Rows.Count - 1 = i Or DataGridView1.Item(e.ColumnIndex, i).Displayed = False Then
                                    siguientes = i - e.RowIndex - 1
                                    Exit For
                                End If
                            Next
    
                            If siguientes = previos Or siguientes - 1 = previos Then
                                'DataGridView1.Item(e.ColumnIndex, i - 1).Value = vbNullString
                                'DataGridView1.Item(Col, i).ContentBounds.Y = DataGridView1.Item(Col, i).ContentBounds.Y - 10
                                e.Graphics.DrawString(CType(e.Value, String), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + 2, StringFormat.GenericDefault)
                            End If
                            'End If
                        End If
    
                        e.Handled = True
                    End Using
                End Using
            End If
        End Sub
    
        Private Sub DataGridView1_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles DataGridView1.Scroll
            'TODO: don't refresh when there are no merged cells
            If e.Type = ScrollEventType.SmallDecrement Or e.Type = ScrollEventType.SmallIncrement Then
                If Not (DataGridView1.FirstDisplayedCell.RowIndex + DataGridView1.DisplayedRowCount(True) = DataGridView1.Rows.Count) Then
                    DataGridView1.Refresh()
                End If
            End If
        End Sub
    

    In the "Tag" property set if you want merge and do DataGridView1.Refresh() to redraw once you set which columns you want to merge


    • Proposed as answer by champaj Tuesday, October 11, 2011 7:50 PM
    Tuesday, October 11, 2011 7:49 PM
  • Greetings All,

    I used the great ideas from the other postings to learn more about the "beast" that is the DataGridView.  I arrived at a fairly simple solution that does what I was looking for with minimal intrution in the event process:

        Private Sub dgvDMS_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgvDMS.CellPainting
    
            If e.ColumnIndex <> 0 Then Exit Sub
    
            'Only the Serial Number column
    
            'Is the value of the next row the same
            If e.RowIndex + 1 < dgvDMS.Rows.Count Then
                If e.Value = dgvDMS.Rows(e.RowIndex + 1).Cells(e.ColumnIndex).Value Then
                    e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None
                End If
            End If
    
            'Is the previous column cell value the same
            If e.RowIndex >= 1 Then
                If e.Value = dgvDMS.Rows(e.RowIndex - 1).Cells(e.ColumnIndex).Value Then
                    e.Graphics.FillRectangle(New SolidBrush(e.CellStyle.BackColor), e.CellBounds)
                    e.PaintBackground(e.CellBounds, False)
                    e.Handled = True
                End If
            End If
    
        End Sub
    
    

    • Proposed as answer by SW-Engineer Wednesday, March 21, 2012 3:24 PM
    Thursday, January 12, 2012 2:23 PM
  • ...or...

    1.- Set the "CellBorderStyle" to "None"

    • Select the DataGridView object with your cursor
    • Find the "CellBorderStyle" property on the Properties window
    • Change its value to "None"

    2.- Create additional thin columns and rows between your current regular columns and rows.  A thickness of 2 will do and is also the minimum allowed.  Make sure you set the "MinimumWidth" property of each column to "2" before setting the "Width" property to "2".

    • Select the DataGridView object with your cursor and click on the tiny arrow on the upper-right corner
    • Select "Edit Columns" from the menu
    • Use intituive common-sense to add thin columns in between each regular column, based on the instructions above
    • ...or... add thin columns and rows programatically

    3.- Manipulate the color of the cells in these extra thin columns and rows to create the illusion of grid-lines.  Use the same color as your other cells to create the illusion of merged cells.

    I used this method to avoid the painful and complicated "DrawLine" method.  Of course, if you copy-paste data from the DataGridView control to excel, the extra columns and rows will also be copied and pasted.  But if you only need it for aestetics as I did, that will not be an issue.

    Friday, May 25, 2012 8:04 AM