Asked by:
Merge datagridview row and column cells

Question
-
All replies
-
how to merge datagridview row and column cells like below image...i need like that only..
Mankatha
- Merged by Bob Wu-MTModerator Monday, April 23, 2012 6:07 AM
-
Few articles which can help you
http://social.msdn.microsoft.com/Forums/en/winformsapplications/thread/93a5364e-0cde-42ca-a030-50f5f00878d3
http://www.codeproject.com/Articles/34037/DataGridVewTextBoxCell-with-Span-Behaviour
http://www.codeproject.com/Questions/152113/How-can-i-merge-DataGridView-Rows-Cells-with-Equal
http://www.codeproject.com/Articles/35844/MergedDataGridView-Control
Gaurav Khanna | Microsoft VB.NET MVP
- Proposed as answer by Bob Wu-MTModerator Monday, April 23, 2012 6:06 AM
- Marked as answer by Bob Wu-MTModerator Wednesday, May 9, 2012 5:10 AM
- Unmarked as answer by Mankatha da Wednesday, May 9, 2012 4:22 PM
-
Duplicate Post
Gaurav Khanna | Microsoft VB.NET MVP
-
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
- Proposed as answer by Bob Wu-MTModerator Monday, April 23, 2012 6:12 AM
- Marked as answer by Bob Wu-MTModerator Wednesday, May 9, 2012 5:10 AM
- Unmarked as answer by Mankatha da Wednesday, May 9, 2012 4:22 PM
-
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