Questo sito utilizza cookie tecnici e di terze parti. Continuando la navigazione sul nostro sito accetti l'uso dei cookie. Per saperne di più leggi l'informativa sui cookie.   


Clonare DataGridView tra form differenti
Ultimo messaggio: 11 gen 2019 17:34 di Stefano-3Soft. 3 Risposte.
Stampa gradevole
Solo gli utenti registrati possono rispondere ad una discussione.
Avatar
Stefano-3Soft
Messaggi: 489
Iscritto dal: 30 apr 2012 11:31
Socio
Socio

02 gen 2019 16:35

ciao a tutti. stavo guardando la seguente discussione

http://www.visual-basic.it/Forum/ta...CzJpVVKjcs

visto che ho un problema analogo (per aiutare l'utente vorrei mostrare la grglia in modalità "estesa") ho provato la soluzione descritta da Diego.

In pratica da un form padre istanzio un form figlio in cui effettuo un riferimento al DataGridView che ho sul padre:

nel padre:

Private Sub btnExpandGrid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExpandGrid.Click

'
' Apre il form per la clonazione della griglia
'
    Using frm As New frmDGVClone(dgvDetails)
        frm.ShowDialog(
Me)
    
End Using End Sub

Il figlio è un form vuoto cioè non contiene nessun DataGridView che viene aggiunto solo durante l'istanziazione.

nel figlio:

Public Class frmDGVClone

Friend Sub New(ByVal mGrid As DataGridView)
    ' This call is required by the Windows Form Designer.
    InitializeComponent()
    
' Add any initialization after the InitializeComponent() call.
    Me.Controls.Add(mGrid)
End Sub
End
 Class


Funziona correttamente. Quando faccio click sul bottone si apre il form figlio e trovo la stessa griglia presente nel form padre (colonne, intestazioni, dati).

Il problema nasce quando chiudo il form figlio. La griglia presente nel padre scompare. Penso sia dovuto al fatto che la griglia nel form figlio è un rifermiento a quella del padre e la distruzione del form figlio si porta dietro l'annullamento anche della griglia.

Come fare per risolverlo?

Grazie

Stefano

 

    Avatar
    Diego Cattaruzza [exMVP]
    Messaggi: 7167
    Iscritto dal: 08 set 2012 12:22
    Team
    Team

    11 gen 2019 12:34

    In effetti non avevo considerato questo grave difetto.

    Quindi devi clonare ogni riga della dgv riferita e aggiungerla alla dgv nuova che avrai costruito vuota con le stesse colonne.

    In pratica, nel costruttore, porrai una riga come questa:

    BuildDGV(mGrid)

    e questo metodo creeerà una nuova dgv con le stesse colonne della dgv riferita e ne aggiungerà le righe clonate.

      Diego Cattaruzza
      ex MVP Visual Basic .Net
      blog: Uncensured
      Avatar
      Stefano-3Soft
      Messaggi: 489
      Iscritto dal: 30 apr 2012 11:31
      Socio
      Socio

      11 gen 2019 15:24

      Grazie Diego per la risposta. Se può interessare a qualcuno il procedimento di clonazione di un DataGridView è il seguente (non è farina del mio sacco l'ho copiato da StackOverflow):

      nel padre:

      Private Sub btnExpandGrid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExpandGrid.Click

      '
      ' Apre il form per la clonazione della griglia
      '
          Using frm As New frmDGVClone(dgvDetails)
              frm.ShowDialog(Me)
          End Using End Sub

      nel figlio:

      Public Class frmDGVClone

      Private TargetGrid As New DataGridView


      Friend Sub New(ByVal SourceGrid As DataGridView)
          ' This call is required by the Windows Form Designer.
          InitializeComponent()
          ' Add any initialization after the InitializeComponent() call.
          Call CloneDataGridView(SourceGrid, TargetGrid)
      End Sub

      Public Sub CloneDataGridView(ByVal sourceGrid As DataGridView, ByRef targetGrid As DataGridView)

      'Copy all rows and cells.
          Dim targetRows = New List(Of DataGridViewRow)

          For Each sourceRow As DataGridViewRow In sourceGrid.Rows
              If (Not sourceRow.IsNewRow) Then
                  Dim targetRow = CType(sourceRow.Clone(), DataGridViewRow)

                  'The Clone method do not copy the cell values so we must do this manually.
                  'See: https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewrow.clone(v=vs.110).aspx

                  For Each cell As DataGridViewCell In sourceRow.Cells
                      targetRow.Cells(cell.ColumnIndex).Value = cell.Value
                  Next

                  targetRows.Add(targetRow)

              End If
          Next

      'Clear target columns and then clone all source columns.

          targetGrid.Columns.Clear()

          For Each column As DataGridViewColumn In sourceGrid.Columns
              targetGrid.Columns.Add(CType(column.Clone(), DataGridViewColumn))
          Next

      'It's recommended to use the AddRange method (if available)
      'when adding multiple items to a collection.

          targetGrid.Rows.AddRange(targetRows.ToArray())

      End Sub
      Private Sub frmDGVClone_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
          Me.Controls.Add(TargetGrid)
          TargetGrid.Dock = DockStyle.Fill
      End Sub
      End
       Class

      Ora però viene il bello...Intercettare tutte le modifiche che vengono fatte sulla griglia e riportarle in quella originale. Penso di fare, nel padre, la stessa clonazione al contrario passando la griglia TARGET come proprietà pubblica.

      Stefano Selmi

       

        Avatar
        Stefano-3Soft
        Messaggi: 489
        Iscritto dal: 30 apr 2012 11:31
        Socio
        Socio

        11 gen 2019 17:34

        Ho fatto anche la parte di ritorno griglia al padre. L'ho implementata con 2 proprietà ReadOnly di cui una mi dice che ci sono state modifiche sulla griglia e l'altra una nuova griglia frutto della clonazione della griglia Target.

        Manca tutto il codice relativo alla gestione delle modifiche sulla griglia e si deve fare attenzione che se si chiude il form con una riga ancora in editing il valore modificato della cella non viene riportato indietro. Quindi prima di chiudere il form verificare se ci sono celle "dirty" e farne il commit.

        Tutto il resto funziona. Se può essere utile a qualcuno ecco il codice:

         

        Public Class frmDGVClone
        Private TargetGrid As New DataGridView
        Private mGridUpdated As Boolean
        Private
         mReturnedGrid As New DataGridView
        Public ReadOnly Property GridUpdated() As Boolean
            Get
               Return mGridUpdated
            
        End Get
        End
         Property
        Public
         ReadOnly Property ReturnedGrid() As DataGridView
            
        Get
               Return mReturnedGrid
            
        End Get
        End
         Property
        Friend
         Sub New(ByVal SourceGrid As DataGridView)
            ' This call is required by the Windows Form Designer.
            InitializeComponent()
            
        ' Add any initialization after the InitializeComponent() call.
        '
        ' Recupero parametri
        ' 1: Griglia ore
        '
            Call CloneDataGridView(SourceGrid, TargetGrid)
        End Sub
        Private
         Sub frmDGVClone_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load
            
        Me.Controls.Add(TargetGrid)
            TargetGrid.Dock = DockStyle.Fill
            mGridUpdated = 
        False
        End
         Sub
        Private
         Sub frmDGVClone_FormClosing(ByVal sender As ObjectByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            
        If mGridUpdated Then
                Call CloneDataGridView(TargetGrid, mReturnedGrid)
            
        Else
                mReturnedGrid = Nothing
            End If
        End
         Sub

        Public Sub CloneDataGridView(ByVal sourceGrid As DataGridView, ByRef targetGrid As DataGridView)
        '
        ' Copy all rows and cells.
        '
            Dim targetRows = New List(Of DataGridViewRow)
            
        For Each sourceRow As DataGridViewRow In sourceGrid.Rows
                
        If (Not sourceRow.IsNewRow) Then
                    Dim targetRow = CType(sourceRow.Clone(), DataGridViewRow)
                    
        'The Clone method do not copy the cell values so we must do this manually.
                    'See: https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewrow.clone(v=vs.110).aspx
                    For Each cell As DataGridViewCell In sourceRow.Cells
                        targetRow.Cells(cell.ColumnIndex).Value = cell.Value
                    
        Next
                    targetRows.Add(targetRow)
                
        End If
            Next
        '
        ' Clear target columns and then clone all source columns.
        '
            targetGrid.Columns.Clear()
            
        For Each column As DataGridViewColumn In sourceGrid.Columns
                targetGrid.Columns.Add(
        CType(column.Clone(), DataGridViewColumn))
            
        Next
        '
        ' It's recommended to use the AddRange method (if available) when adding multiple items to a collection.
        '
            targetGrid.Rows.AddRange(targetRows.ToArray())
        End Sub

        End
         Class
          Solo gli utenti registrati possono rispondere ad una discussione.