Drag & Drop entre DataGridView

Résolu
Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 - 14 sept. 2022 à 14:57
Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 - 16 sept. 2022 à 22:30

Bonjour,

Dans un petit programme en VB.net, j'ouvre 2 Form, chacun contenant un DataGridView (F1 avec DGV1 et F2 avec DGV1).
Je peux transférer des données de l'un à l'autre par le code (via un DataTable public), je peux faire du Copier-Coller également.
Je souhaiterais pouvoir en plus, glisser des lignes sélectionnées dans un DataGridView et les déposer dans l'autre.

Je trouve quelques discussions sur le Drag & Drop entre DataGridView, mais elles ne concernent que du Drag-Drop sur un même Form et de plus, aucune ne m'apporte de code qui fonctionne vraiment.

Si quelqu'un a une idée ...

Merci d'avance,

Sam

5 réponses

Whismeril Messages postés 19082 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 9 juillet 2024 658
14 sept. 2022 à 15:57

Bonjour

un datatable public n'est pas une bonne pratique ça expose tes données à n'importe qui (y compris un programme extérieur).

Tu trouveras ici plusieurs façons de faire plus conseillées

https://codes-sources.commentcamarche.net/faq/11107-interactions-entre-form-en-net-c-et-vb-net

Pour ton problème à proprement parlé, j'ai peut-être une solution à base de collection de classe métier, mais ça t'obligerait à revoir ton architecture pour ne plus te servir de datatable (sauf éventuellement à la lecture initiale de ta base de données et à l'écriture des updates).


Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 1
14 sept. 2022 à 16:34

Merci Whismeril pour le déplacement de la discussion. Quand j'ai dû désigner le forum, j'ai vu C#/.Net d'une part et VB d'autre part. Ne souhaitant pas le C# ni le VB 6.0, j'ai quand même opté pour C#/.Net.

Pour ce qui est du DataTable public, je connais le bien fondé de ta remarque. Mais jusque-là, c'est expérimental. A terme, cela doit devenir une classe. Mais il faudra bien qu'elle soit partagée car son but est de mettre les mêmes données à la disposition de plusieurs instances actives au même moment. Ces données peuvent être modifiées dans plusieurs instances d'un même Form.

Pas de problème pour le code puisque chaque instance accède au même DataTable. Pour le Copier-Coller, il y a le Clipboard mais l'usage du DataTable déjà présent est très simple.

Pour le Drag & Drop, cela ne fonctionne plus car je ne sais pas comment le charger et le relire pendant l'opération. Il ne m'est pas interdit de changer de technique, rien ne m'oblige d'utiliser le DataTable dans ce cas. Alors, si tu as une idée, je suis preneur ... 

Merci d'avance ...

Sam

0
Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 1
Modifié le 16 sept. 2022 à 23:49

Bonsoir,

Mon projet test est terminé. Il est possible de copier des sélections de lignes d'un DataGridView vers lui-même, ou vers son "avatar" d'une autre instance, ou aussi vers un autre DataGridView de la même instance ou d'une autre.

Soit un Form nommé FDragDrop contenant 2 DataGridView DGV1 et DGV2. Le DGV1 est chargé par des données de test lors de son Load. Le DoubleClick du Form ouvre une nouvelle instance, laquelle peut aussi être double-cliquée, et ainsi de suite ...

Voici le code de ce Form :

Public Class FDragDrop

    Private Sub Form1_DoubleClick(sender As Object, e As EventArgs) Handles Me.DoubleClick
        Dim F2 As New FDragDrop
        F2.Show()
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Pour les tests
        DGV1.Columns.Add("Col1", "Col.1")
        DGV1.Columns.Add("Col2", "Col.2")
        DGV1.Rows.Add("1", "az")
        DGV1.Rows.Add("2", "aze")
        DGV1.Rows.Add("3", "azer")
        DGV1.Rows.Add("4", "azert")
        DGV1.Rows.Add("5", "azerty")
        DGV2.Columns.Add("Col1", "Col.1")
        DGV2.Columns.Add("Col2", "Col.2")

        ' Réglages nécessaires
        DGV1.AllowDrop = True
        DGV1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
        DGV2.AllowDrop = True
        DGV2.SelectionMode = DataGridViewSelectionMode.FullRowSelect
    End Sub

    Dim SelectionFinie As Boolean

    ' Sélectionner et démarrer le DragDrop à partir de DGV1
    Private Sub DGV1_MouseDown(sender As Object, e As MouseEventArgs) Handles DGV1.MouseDown
        If (e.Button = MouseButtons.Left) Then
            If SelectionFinie Then
                DGV1.DoDragDrop(DGV1.SelectedRows, DragDropEffects.Copy)
                SelectionFinie = False
            Else
                DGV1.ClearSelection()
            End If
        Else
            SelectionFinie = False
        End If
    End Sub

    ' Sélectionner et démarrer le DragDrop à partir de DGV2
    Private Sub DGV2_MouseDown(sender As Object, e As MouseEventArgs) Handles DGV2.MouseDown
        If (e.Button = MouseButtons.Left) Then
            If SelectionFinie Then '
                DGV2.DoDragDrop(DGV2.SelectedRows, DragDropEffects.Copy)
                SelectionFinie = False
            Else
                DGV2.ClearSelection()
            End If
        Else
            SelectionFinie = False
        End If
    End Sub

    ' Fin de sélection sur  DGV1
    Private Sub DGV1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV1.MouseUp
        If (DGV1.SelectedRows.Count > 0) Then
            SelectionFinie = True
        End If
    End Sub

    ' Fin de sélection sur  DGV2
    Private Sub DGV2_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV2.MouseUp
        If (DGV2.SelectedRows.Count > 0) Then
            SelectionFinie = True
        End If
    End Sub

    ' Vérifier la présence de données à l'entrée du processus de Drag-Drop lancé de DGV1
    Private Sub DGV1_DragEnter(sender As Object, e As DragEventArgs) Handles DGV1.DragEnter
        If (e.Data Is Nothing) Then
            e.Effect = DragDropEffects.None
        Else
            e.Effect = DragDropEffects.Copy
        End If
    End Sub

    ' Vérifier la présence de données à l'entrée du processus de Drag-Drop lancé de DGV2
    Private Sub DGV2_DragEnter(sender As Object, e As DragEventArgs) Handles DGV2.DragEnter
        If (e.Data Is Nothing) Then
            e.Effect = DragDropEffects.None
        Else
            e.Effect = DragDropEffects.Copy
        End If
    End Sub

    ' Déposer dans DGV1 les données capturées par le processus Drag-Drop
    Private Sub DGV1_DragDrop(sender As Object, e As DragEventArgs) Handles DGV1.DragDrop
        If (e.Data IsNot Nothing) Then
            Dim Selection As DataGridViewSelectedRowCollection = CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
            Dim NCol As Integer = Selection(0).Cells.Count
            For Each R As DataGridViewRow In Selection
                Dim NR As DataGridViewRow = CType(R.Clone(), DataGridViewRow)
                For C As Integer = 0 To NCol - 1
                    NR.Cells(C).Value = R.Cells(C).Value
                Next
                DGV1.Rows.Add(NR)
            Next
        End If
        DGV1.ClearSelection()
    End Sub

    ' Déposer dans DGV2 les données capturées par le processus Drag-Drop
    Private Sub DGV2_DragDrop(sender As Object, e As DragEventArgs) Handles DGV2.DragDrop
        If (e.Data IsNot Nothing) Then
            Dim Selection As DataGridViewSelectedRowCollection = CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
            Dim NCol As Integer = Selection(0).Cells.Count
            For Each R As DataGridViewRow In Selection
                Dim NR As DataGridViewRow = CType(R.Clone(), DataGridViewRow)
                For C As Integer = 0 To NCol - 1
                    NR.Cells(C).Value = R.Cells(C).Value
                Next
                DGV2.Rows.Add(NR)
            Next
        End If
        DGV2.ClearSelection()
    End Sub

End Class

A toutes fins utiles, je dépose ce projet de test sur Dropbox pour quelques temps (j'espère ne pas contrevenir aux règles du forum) : https://www.dropbox.com/s/q5uyvdbri3xmfis/DragDrop.zip?dl=0

Cordialement,

Sam

Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 1
Modifié le 16 sept. 2022 à 17:28

Bonjour,

Mon problème de Drag-Drop entre DataGridView, même d'instances différentes, est résolu sans l'usage d'un DataTable Public, mais bien avec le e.Data inclus "d'office" dans l'évènement DrogDrop. 

Voici les principaux extraits de codes :

    Dim SelectionFinie As Boolean = False

    Private Sub DGV1_MouseDown(sender As Object, e As MouseEventArgs) Handles DGV1.MouseDown

        If (e.Button = MouseButtons.Left) Then
            If SeectionFinie Then
                DGV1.DoDragDrop(DGV1.SelectedRows, DragDropEffects.Copy)
                SelectionFinie = False
            End If
        End If
    End Sub

    Private Sub DGV1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV1.MouseUp
        If (DGV1.SelectedRows.Count > 0) Then
            SelectionFinie = True
        End If
    End Sub

    Private Sub DGV2_DragEnter(sender As Object, e As DragEventArgs) Handles DGV2.DragEnter
        If (e.Data IsNot Nothing) Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.None
        End If
    End Sub

    Private Sub DGV2_DragDrop(sender As Object, e As DragEventArgs) Handles DGV2.DragDrop
        If SelectionFinie Then
            If (e.Data IsNot Nothing) Then
                Dim Selection As DataGridViewSelectedRowCollection = CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
                Dim NCol As Integer = selected(0).Cells.Count
                For Each R As DataGridViewRow In Selection
                    Dim NR As DataGridViewRow = CType(R.Clone(), DataGridViewRow)
                    For C As Integer = 0 To NCol - 1
                        NR.Cells(C).Value = R.Cells(C).Value
                    Next
                    DGV2.Rows.Add(NR)
                Next
            End If
        End If
    End Sub

Cela fonctionne presque parfaitement compte tenu de a question initiale mais reste à améliorer.

Non seulement il est possible de copier de DGV1 vers DGV2 de la même instance et de DGV1 vers DGV2 d'une autre instance, je voudrais compléter de sorte à pouvoir copier de DGV2 vers DGV1, mais aussi de DGV1 vers DGV1 et de DGV2 vers DGV2, dans la même instance ou d'une instance à l'autre. 

En fait, je veux imiter Excel : quand il y a plusieurs feuilles XLS visibles, il est possible de Drag-Drop de l'une à l'autre et il est toujours possible de Drag-Drop dans une même feuille.

Si quelqu'un a une idée ...

Bon week-end,

Sam

Whismeril Messages postés 19082 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 9 juillet 2024 658
16 sept. 2022 à 17:29

Bonsoir

je n'avais pas encore eu le temps de me pencher sur ta question.

Tant mieux si tu l'as partiellement résolue.
 

Pour tes prochains messages, merci de sélectionner Basic dans l'interface d'extraits de code.


Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Sam_Placi Messages postés 38 Date d'inscription mercredi 29 juin 2022 Statut Membre Dernière intervention 22 mai 2023 1
16 sept. 2022 à 18:38

Bonsoir,

J'ai modifié le libellé de mon raccourci vers ce site en y intégrant BASIC, j'espère que cela me permettra de m'en souvenir à l'avenir.

Peut-être aurais-tu une astuce qui me permettrait d'avancer encore.

Ce qui me bloque actuellement est que la sélection dans le DataGridView "source" reste active après l'évènement DragDrop du DataGridView "Cible". Ce détail m'empêche de faire correctement une nouvelle sélection dans le même DataGridView "source" car à mon etoru sur ce DGV, il y exécute le DragDrop et y colle (ajoute)  les lignes de la sélection. Le ClearSelection n'a aucun effet sur cette sélection, c'est comme si elle était verrouillée par le processus du Drag-Drop.

Si tu as une idée ...

En tout cas, encore merci pour ton commentaire d'avant-hier, il m'a permis de chercher autre chose que mon DataTable publique.

Cordialement,

Sam

Rejoignez-nous