none
Merge datagridview row and column cells

    Question

  • how to merge datagridview row and column cells like below image...i need like that only..

    Mankatha

    Saturday, April 21, 2012 1:23 PM

All replies

  • how to merge datagridview row and column cells like below image...i need like that only..

    Mankatha

    Saturday, April 21, 2012 1:23 PM
  • Place the code below into a new code module, build the project, add the DataGridView onto your form then for a test see the second code block below. What is important is that the data source for the GroupByGrid is sorted on the repeating column (where for you it is CompanyName). Note I sort on Column1 in the second code block as that is the repeating column.

    ''' <summary>
    ''' Original author
    ''' http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/a44622c0-74e1-463b-97b9-27b87513747e#faq8
    ''' </summary>
    ''' <remarks>
    ''' Original code was in C Sharp, I converted and tweaked some code
    ''' which did not compile under VB.NET
    ''' </remarks>
    Public Class GroupByGrid
        Inherits DataGridView
        Protected Overrides Sub OnCellFormatting(ByVal args As DataGridViewCellFormattingEventArgs)
            MyBase.OnCellFormatting(args)
            ' First row always displays
            If args.RowIndex = 0 Then
                Return
            End If
            If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then
                args.Value = String.Empty
                args.FormattingApplied = True
            End If
        End Sub
        Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal colIndex As Integer) As Boolean
            Dim currCell As DataGridViewCell = Rows(rowIndex).Cells(colIndex)
            Dim prevCell As DataGridViewCell = Rows(rowIndex - 1).Cells(colIndex)
            If (currCell.Value Is prevCell.Value) OrElse (currCell.Value IsNot Nothing AndAlso prevCell.Value IsNot Nothing AndAlso currCell.Value.ToString() = prevCell.Value.ToString()) Then
                Return True
            Else
                Return False
            End If
        End Function
        Protected Overrides Sub OnCellPainting(ByVal args As DataGridViewCellPaintingEventArgs)
            MyBase.OnCellPainting(args)
            args.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None
            ' Ignore column and row headers and first row
            If args.RowIndex < 1 OrElse args.ColumnIndex < 0 Then
                Return
            End If
            If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then
                args.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None
            Else
                args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top
            End If
        End Sub
    End Class
    Using dt As New DataTable()
        dt.Columns.AddRange(New DataColumn() _
            { _
                New DataColumn("Column1", GetType(System.String)), _
                New DataColumn("Column2", GetType(System.String)), _
                New DataColumn("Column3", GetType(System.String)) _
            } _
        )
        dt.Rows.Add(New Object() {"aleksy", "Rugby", "!!!"})
        dt.Rows.Add(New Object() {"aleksander", "football", "ASDAS"})
        dt.Rows.Add(New Object() {"aleksy", "hurtles", "1121"})
        dt.Rows.Add(New Object() {"bazyli", "baseball", "000"})
        dt.Rows.Add(New Object() {"aleksander", "car racing", "LSDFJ"})
        dt.Rows.Add(New Object() {"bazyli", "boxing", "2kefrjek"})
        dt.Rows.Add(New Object() {"bazyli", "cricket", "salka"})
        dt.Rows.Add(New Object() {"grzegorz", "volleyball", "asd"})
        dt.Rows.Add(New Object() {"aleksy", "boxing", "wsw"})
        dt.DefaultView.Sort = "Column1"
        GroupByGrid1.DataSource = dt
    End Using



    KSG

    Monday, April 23, 2012 2:31 AM
    Moderator
  • Same behavior, but isolated in a Custom Column, called DataGridViewMergedTextBoxColumn.

    This way, we can choose in wich columns we need to have the Merge function.

    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Windows.Forms
    Imports System.Drawing
    Imports System.ComponentModel
    
    Public Class DataGridViewMergedTextBoxColumn
        Inherits DataGridViewTextBoxColumn
        Public Sub New()
            CellTemplate = New DataGridViewMergedTextBoxCell()
        End Sub
    End Class
    
    
    Class DataGridViewMergedTextBoxCell
        Inherits DataGridViewTextBoxCell
    
        Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal colIndex As Integer) As Boolean
            If rowIndex = 0 Then Return False
            Dim currCell As DataGridViewCell = Me.DataGridView.Rows(rowIndex).Cells(colIndex)
            Dim prevCell As DataGridViewCell = Me.DataGridView.Rows(rowIndex - 1).Cells(colIndex)
            If (currCell.Value Is prevCell.Value) OrElse (currCell.Value IsNot Nothing AndAlso prevCell.Value IsNot Nothing AndAlso currCell.Value.ToString() = prevCell.Value.ToString()) Then
                Return True
            Else
                Return False
            End If
        End Function
    
    
        Protected Overrides Function GetFormattedValue(value As Object, rowIndex As Integer, ByRef cellStyle As DataGridViewCellStyle, valueTypeConverter As TypeConverter, formattedValueTypeConverter As TypeConverter, context As DataGridViewDataErrorContexts) As Object
    
            ' First row always displays
            If rowIndex > 0 AndAlso IsRepeatedCellValue(rowIndex, ColumnIndex) Then
                Return String.Empty
            else 
                Return MyBase.GetFormattedValue(value, rowIndex, cellStyle, valueTypeConverter, formattedValueTypeConverter, context)
            End If
        End Function
        Protected Overrides Sub Paint(g As System.Drawing.Graphics, clipBounds As System.Drawing.Rectangle, cellBounds As System.Drawing.Rectangle, rowIndex As Integer, cellState As DataGridViewElementStates, value As Object, _
            formattedValue As Object, errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, paintParts As DataGridViewPaintParts)
    
            advancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None
    
            If IsRepeatedCellValue(rowIndex, ColumnIndex) Then
                advancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None
            Else
                advancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.Single
            End If
    
            MyBase.Paint(g, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
    
        End Sub
    End Class


    • Edited by Felice Ferri Monday, August 8, 2016 4:52 AM
    • Proposed as answer by Felice Ferri Monday, August 8, 2016 4:52 AM
    Monday, August 8, 2016 4:51 AM