IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Drag & Drop entre DataGridView


Sujet :

VB.NET

  1. #1
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut Drag & Drop entre DataGridView
    Bonjour,

    Dans un petit programme, 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

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Sur la grille de l'écran 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        Private Sub DataGridView1_MouseDown(sender As Object, e As MouseEventArgs) Handles DataGridView1.MouseDown
            If (e.Button = MouseButtons.Left) AndAlso (DataGridView1.CurrentRow IsNot Nothing) Then
                DoDragDrop(DataGridView1.CurrentRow, DragDropEffects.Copy)
            End If
        End Sub

    Sur la grille de l'écran 2 (en partant du principe que les colonnes sont identiques) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        Private Sub DataGridView1_DragEnter(sender As Object, e As DragEventArgs) Handles DataGridView1.DragEnter
            If (e.Data IsNot Nothing) Then
                e.Effect = DragDropEffects.Copy
            Else
                e.Effect = DragDropEffects.None
            End If
        End Sub
     
        Private Sub DataGridView1_DragDrop(sender As Object, e As DragEventArgs) Handles DataGridView1.DragDrop
            If (e.Data IsNot Nothing) Then
                Dim row As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)
                DataGridView1.Rows.Add(row.Cells(0).Value, row.Cells(1).Value)
            End If
        End Sub
    Edit : Penser à mettre AllowDrop à true sur la grille de l'écran 2

  3. #3
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut
    Merci Popo, cela m'avance déjà beaucoup.

    Mais, si je n'abuse pas, il me reste 2 détails :
    1. Je voudrais pouvoir copier une ligne et ensuite, une autre. Or après le DragDrop d'une ligne, il ne fonctionne plus. Il doit bien y avoir une manière de le réinitialiser.
    2. Le code que tu m'envoies me permet de sélectionner une ligne pour le DragDrop or je voudrais utiliser une sélection de plusieurs lignes. J'ai remplacé DoDragDrop(DGV1.CurrentRow, DragDropEffects.Copy) par DoDragDrop(DGV1.SelectedRows, DragDropEffects.Copy), mais ça ne va plus au niveau du Drop.


    Cordialement,

    Sam

  4. #4
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut
    @Popo

    Grâce à ton code, j'ai une solution !

    Toutefois, je voudrais qu'elle soit critiquée ...
    En effet, j'utilise une variable publique et 2 méthodes également publiques, le tout écrit dans un Module pour le temps des essais. Cela devra devenir une Classe mais la variable et ces méthode devront être disponibles pour toutes les instances actives à un moment donné. Je me demande dans quelle mesure cette variable publique (de type DataTable) ne fait pas double emploi avec le e.Data.
    Par ailleurs, je peux faire des DragDrop successifs sans problème, je ne sais pas pourquoi ça ne fonctionnait pas ainsi tout à l'heure.

    Dans mon code ci-dessous, le Module appelé M_DataTable contient les données publiques :
    MisDatosTmp As DataTable qui est le DataTable accessible de toutes les instances
    et les méthodes
    CopiarParteDGVEnDTT et CopiarParteDTTEnDGV qui servent respectivement à copier les lignes sélectionnées du DGV dans le DataTable et inversement. La méthode CopiarParteDTTEnDGV crée les colonnes dans le DGV cible si nécessaire.

    Le Form1 contient 2 DGV et le DoubleClick du Form ouvre une autre insatnce de lui-même. Le dragDrop fonctionne du DGV1 vers le DGV2, qu'ils soient sur la même instance ou pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    Public Class Form1
     
        Private SeleccionTerminada As Boolean
     
        Private Sub Form1_DoubleClick(sender As Object, e As EventArgs) Handles Me.DoubleClick
            Dim F2 As New Form1
            F2.Show()
        End Sub
     
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            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.AllowDrop = True
     
        End Sub
     
        Private Sub DGV1_MouseDown(sender As Object, e As MouseEventArgs) Handles DGV1.MouseDown
            If (e.Button = MouseButtons.Left) AndAlso (DGV1.SelectedRows.Count > 0) Then
                If SeleccionTerminada Then
                    M_DataTable.CopiarParteDGVEnDTT(DGV1)
                    DGV1.DoDragDrop(DGV1.SelectedRows, DragDropEffects.Copy)
                End If
            End If
        End Sub
     
        Private Sub DGV1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DGV1.MouseUp
            SeleccionTerminada = True
        End Sub
     
        Private Sub DGV2_DragEnter(sender As Object, e As DragEventArgs) Handles DGV2.DragEnter
            ' If (e.Data IsNot Nothing) Then
            If M_DataTable.MisDatosTmp.Rows.Count > 0 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 (e.Data IsNot Nothing) Then
            If M_DataTable.MisDatosTmp.Rows.Count > 0 Then
                M_DataTable.CopiarParteDTTEnDGV(DGV2)
                e.Effect = DragDropEffects.None
            End If
     
        End Sub
     
    End Class
    Merci d'avance pour ta critique.

    Sam

  5. #5
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Techniquement, comme tu l'as écrit, cela revient effectivement au même et e.Data ne te sert pas vraiment.
    Donc cela fonctionne et tu as pu le constater par toi même.

    En pratique, j'aurais quelques réserves.
    Déjà, puisque MisDatosTmp est une ressource partagée, le fait d'y déposer ta sélection va impacter tous les objets qui l'utilisent.

    Au delà de cet aspect, il y a quelques dogmes, qui si tu les respectes, éviteront pas mal d'ennuis sur des projets plus conséquents.
    En ce qui concerne ton cas particulier, il y a au moins deux que tu transgresses.

    1. Ne pas réinventer la roue inutilement :
    Il faut penser à la personne qui passera derrière toi.
    Si l'objectif de cette classe est uniquement de réaliser un passe-plat pour faire du Drag-and-Drop, alors cette classe ne sert à rien.
    Cela réinvente ce qui existe nativement dans le Framework (e.Data).
    C'est donc inutile mais surtout perturbant pour un autre développeur.

    2. Le principe de responsabilité unique :
    Si cette classe a un autre objectif, alors ce n'est pas une bonne idée de la détourner de cet objectif pour faire du Drag-and-Drop.
    https://fr.wikipedia.org/wiki/Princi...t%C3%A9_unique

  6. #6
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut
    @Popo

    Merci pour ton analyse.

    C'est vrai que M_DataTable et ne sert que ce projet et qu'effectivement, je récris ce qui existe déjà (e.data). La raison est que je ne parviens pas à utiliser e.data pour passer un lot de lignes sélectionnées (DGV1.SelectedRows) ou plus exactement, je ne parviens pas à les récupérer dans la méthode DGV2_DragDrop.

    Je cherche encore ...

    Bonne soirée,

    Sam

  7. #7
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 667
    Points : 5 235
    Points
    5 235
    Par défaut
    Je crois deviner ton problème.
    De la même manière que j'ai converti le contenu de e.Data en DataGridViewRow afin de pouvoir l'utiliser pour atteindre les cellules, il faut le convertir dans le type de SelectedRows, c'est-à-dire DataGridViewSelectedRowCollection.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim selected As DataGridViewSelectedRowCollection = CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection))
    De cette manière, tu pourras le manipuler comme je suppose que tu as dû le faire dans CopiarParteDGVEnDTT.

  8. #8
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut
    Bonjour Popo,

    Encore un fois un grand merci.

    Ton code m'a permis de travailler sans utiliser le DataTable. J'ai eu des difficultés à placer les Rows de la collection selected dans le DGV2 car je recevais un message "La ligne appartient déjà à un DataGridView".

    Voici le code en l'état actuel (il me reste à traiter le cas où le DGV cible n'a encore aucune colonne mais ce sera facile, j'ai déjà ce qu'il faut dans la méthode CopiarParteDTTEnDGV() devenue inutile) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        Private Sub DGV2_DragDrop(sender As Object, e As DragEventArgs) Handles DGV2.DragDrop
            If (e.Data IsNot Nothing) Then
                Dim selected As DataGridViewSelectedRowCollection = CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
                Dim NCol As Integer = selected(0).Cells.Count
                ' Ajouter ici la création des colonnes du DGV2 si nécessaire
                For Each R As DataGridViewRow In selected
                    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 Sub
    Très bonne journée,

    Sam

  9. #9
    Membre habitué Avatar de Sam Placi
    Homme Profil pro
    Développeur occasionnel
    Inscrit en
    Octobre 2019
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur occasionnel

    Informations forums :
    Inscription : Octobre 2019
    Messages : 68
    Points : 129
    Points
    129
    Par défaut
    Bonsoir,

    Grace à Popo, 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 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    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
     
        ' Définir le type de Drag-Drop au début du processus 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
     
        ' Définir le type de Drag-Drop au début du processus 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
    Cordialement,

    Sam

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Drag & Drop entre 2 DataGridView
    Par kritopal dans le forum Windows Forms
    Réponses: 2
    Dernier message: 31/01/2011, 07h31
  2. Drag&Drop entre deux zones de liste
    Par Herman dans le forum IHM
    Réponses: 1
    Dernier message: 28/06/2007, 19h14
  3. OLE , drag & drop entre 2 CListCtrl ?
    Par gabule dans le forum MFC
    Réponses: 1
    Dernier message: 26/04/2007, 09h55
  4. Drag&Drop entre un panel et un JTextField
    Par theBrave dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 04/04/2006, 14h25
  5. Drag & Drop entre 2 listBox : transfert items
    Par netah25 dans le forum C++Builder
    Réponses: 2
    Dernier message: 09/01/2006, 10h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo