none
DGV Clone RRS feed

  • Question

  • Hi All

    I'm trying to clone a DGV (with just 3 rows) using this code

     Public Sub CloneDGV(ByRef pdgv As DataGridView)
    
            DGVClone = New DataGridView
            For Each Col As DataGridViewColumn In pdgv.Columns
                DGVClone.Columns.Add(DirectCast(Col.Clone, DataGridViewColumn))
            Next
            Dim row As New DataGridViewRow()
            For i As Integer = 0 To pdgv.Rows.Count - 1
                row = DirectCast(pdgv.Rows(i).Clone(), DataGridViewRow)
                Dim intColIndex As Integer = 0
                For Each cell As DataGridViewCell In pdgv.Rows(i).Cells
                    row.Cells(intColIndex).Value = cell.Value
                    intColIndex += 1
                Next
                DGVClone.Rows.Add(row)
            Next
            MessageBox.Show(pdgv.RowCount.ToString & " " & DGVClone.RowCount.ToString)
    
        End Sub

    At the end of Sub I get two  value for rows count

    The original pDGV has 3 rows, The DGVClone as 4 rows. How is it possible ?

    The loop thru row is rigth !

    What I found is that after COLUMNs Loop the DGVClone has already 1 row.

    Monday, July 9, 2018 2:19 PM

Answers

  • I would keep the code for this as much as possible out of the form.

    Public Class DataGridViewCloner
        Public Function Cloner(pDgv As DataGridView) As DataGridView
            Dim newDataGridView As New DataGridView
            newDataGridView.CloneColumns(pDgv)
            pDgv.CloneAllRows(newDataGridView)
            Return newDataGridView
        End Function
    End Class

    Code module

    Public Module Extensions
        <DebuggerStepThrough()>
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneRowWithValues(ByVal pRow As DataGridViewRow, ByVal pDgvTarget As DataGridView)
            If pRow.IsNewRow Then
                Exit Sub
            End If
    
            Dim Results As DataGridViewRow = CType(pRow.Clone(), DataGridViewRow)
    
            For Row As Int32 = 0 To pRow.Cells.Count - 1
                Results.Cells(Row).Value = pRow.Cells(Row).Value
            Next
    
            pDgvTarget.Rows.Add(Results)
    
        End Sub
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneAllRows(pDgvWithRows As DataGridView, pDgvTarget As DataGridView)
            For Each row As DataGridViewRow In pDgvWithRows.Rows
                row.CloneRowWithValues(pDgvTarget)
            Next
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="pDgvTarget">DataGridView to populate</param>
        ''' <param name="pDgvWithRows">DataGridView to copy from</param>
        ''' <param name="NameToExclude">Used to exclude a column</param>
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneColumns(ByVal pDgvTarget As DataGridView, ByVal pDgvWithRows As DataGridView, Optional NameToExclude As String = "")
    
            If pDgvTarget.ColumnCount = 0 Then
                For Each c As DataGridViewColumn In pDgvWithRows.Columns
                    pDgvTarget.Columns.Add(CType(c.Clone, DataGridViewColumn))
                Next
                If Not String.IsNullOrWhiteSpace(NameToExclude) Then
                    pDgvTarget.Columns(NameToExclude).Visible = False
                End If
            End If
    
        End Sub
    
    End Module
    

    Use it

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim ops As New DataGridViewCloner
        Dim dgv = ops.Cloner(DataGridView1)
    End Sub


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by Claudio111 Tuesday, July 17, 2018 11:11 AM
    Monday, July 9, 2018 3:15 PM
    Moderator

  • The    DGV.AllowUserToAddRows = False in the original DGV


    Then set it to false in the clone as well and your row count should match as expected.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Claudio111 Tuesday, July 17, 2018 11:12 AM
    Monday, July 9, 2018 4:52 PM
    Moderator

All replies

  • What is the "AllowUsersToAddRows" property for each DGV?  Keep in mind that the "new row" counts as a row.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, July 9, 2018 2:29 PM
    Moderator
  • Hi

    Seems you are copying the NewRow from source DGV which would be the extra blank row in destination DGV.

    All that you need to do is to ignore the row with index of NewRowIndex and your DGV row counts would be equal.



    Regards Les, Livingston, Scotland

    Monday, July 9, 2018 2:56 PM
  • The original DGV is bound to BS bound to DataTable (from SQL)

    When the Original DGV has been filled it is passed to Sub CloneDGV as it is

    The    DGV.AllowUserToAddRows = False in the original DGV


    Monday, July 9, 2018 3:12 PM
  • I would keep the code for this as much as possible out of the form.

    Public Class DataGridViewCloner
        Public Function Cloner(pDgv As DataGridView) As DataGridView
            Dim newDataGridView As New DataGridView
            newDataGridView.CloneColumns(pDgv)
            pDgv.CloneAllRows(newDataGridView)
            Return newDataGridView
        End Function
    End Class

    Code module

    Public Module Extensions
        <DebuggerStepThrough()>
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneRowWithValues(ByVal pRow As DataGridViewRow, ByVal pDgvTarget As DataGridView)
            If pRow.IsNewRow Then
                Exit Sub
            End If
    
            Dim Results As DataGridViewRow = CType(pRow.Clone(), DataGridViewRow)
    
            For Row As Int32 = 0 To pRow.Cells.Count - 1
                Results.Cells(Row).Value = pRow.Cells(Row).Value
            Next
    
            pDgvTarget.Rows.Add(Results)
    
        End Sub
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneAllRows(pDgvWithRows As DataGridView, pDgvTarget As DataGridView)
            For Each row As DataGridViewRow In pDgvWithRows.Rows
                row.CloneRowWithValues(pDgvTarget)
            Next
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="pDgvTarget">DataGridView to populate</param>
        ''' <param name="pDgvWithRows">DataGridView to copy from</param>
        ''' <param name="NameToExclude">Used to exclude a column</param>
        <Runtime.CompilerServices.Extension()>
        Public Sub CloneColumns(ByVal pDgvTarget As DataGridView, ByVal pDgvWithRows As DataGridView, Optional NameToExclude As String = "")
    
            If pDgvTarget.ColumnCount = 0 Then
                For Each c As DataGridViewColumn In pDgvWithRows.Columns
                    pDgvTarget.Columns.Add(CType(c.Clone, DataGridViewColumn))
                Next
                If Not String.IsNullOrWhiteSpace(NameToExclude) Then
                    pDgvTarget.Columns(NameToExclude).Visible = False
                End If
            End If
    
        End Sub
    
    End Module
    

    Use it

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim ops As New DataGridViewCloner
        Dim dgv = ops.Cloner(DataGridView1)
    End Sub


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by Claudio111 Tuesday, July 17, 2018 11:11 AM
    Monday, July 9, 2018 3:15 PM
    Moderator
  • Thanks Karen,

    One more question

    After cloning a DGV, if I change a cell value on CloneDGV  , does the same Cell change also in Original DGV ?

    Monday, July 9, 2018 4:41 PM
  • Thanks Karen,

    One more question

    After cloning a DGV, if I change a cell value on CloneDGV  , does the same Cell change also in Original DGV ?

    Nothing links the two DataGridView controls together so the short answer is no. You would need to subscribe to an event in the DataGridView that changes and then update the other DataGridView.

    If the original DataGridView had it's DataSource set to a DataTable then set the second DataGridView to the same DataTable then they will see each others changes in theory.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Monday, July 9, 2018 4:51 PM
    Moderator

  • The    DGV.AllowUserToAddRows = False in the original DGV


    Then set it to false in the clone as well and your row count should match as expected.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Claudio111 Tuesday, July 17, 2018 11:12 AM
    Monday, July 9, 2018 4:52 PM
    Moderator
  • @Karen,

    Why are you doing this?  Sure this might be a better way in your opinion, but at the end of the day, there is nothing wrong with the way the OP did it and your reply doesn't address the issue being asked about at all.  If you wanted to add value to the thread, your example should go through and set all of the properties on the DGV clone to the same values as the original.  As it is, your post is little more than fancy noise in the thread, dragging the OP away from their actual issue and detracting from posts that do address the issue.

    I'm sorry to have to do this... your posts on data related questions are often quite useful.  But in this case it is a distraction.  Please try to stay focused on what the OP is asking and add your preferences as an aside.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, July 9, 2018 5:06 PM
    Moderator
  • I'm sorry, they are few months I started with Visual Basic and DataGridview.

    I was able to build a User Control,to filter rows in DGV based on Column value, and the result is good

    Now I try to Group DGV rows and add Total for each Numeric Column

    Really, now i don't know wich is the best way to do it. I started to use DGVGrouper form codeproject that is very nice but daos not give group totals for numeric column. 

    Since DGVGrouper in is C# and is not possible to convert in Vb.net I decided to do it by myself in some way

    So now I'm just trying 

    Monday, July 9, 2018 6:00 PM
  • @Claudio:

    Did you see my previous reply about setting AllowUsersToAddRows to false in the clone DGV?  If you set that property to False after creating the new grid you should get the same row count as the original grid using the code you originally posted.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, July 9, 2018 6:42 PM
    Moderator
  • yes Reed Thank you.

    I cloned in the rigth way the dgv

    Monday, July 9, 2018 6:59 PM
  • yes Reed Thank you.

    I cloned in the rigth way the dgv


    So is your issue resolved?  Are you getting the expected row count now?  If so, please close this thread by clicking the Mark As Answer link at the bottom of the post or posts which solved your issue.

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, July 9, 2018 7:33 PM
    Moderator
  • I was focused on the question being asked and see nothing wrong with what I have presented. The objective was to move as much of the operation as possible from the form using code I didn't write for this post but had already. Distraction, personally I didn't see it that way or I would never had posted the code.

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Monday, July 9, 2018 7:36 PM
    Moderator
  • What you presented is a refactoring of the OPs code and doesn't address the issue.

    The question ("The original pDGV has 3 rows, The DGVClone as 4 rows. How is it possible ?") showed that the new (cloned) grid had too many rows.  That means the old grid probably had the new row turned off (which I asked and they verified).  So the solution is in turning off the new row in the cloned grid, not skipping the new row in the existing grid (because it wasn't there).

    I don't want to start a debate or drag this thread further off course... we can just leave it at that.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, July 9, 2018 7:56 PM
    Moderator