Access
 sql >> Base de données >  >> RDS >> Access

Réorganiser les nœuds TreeView par glisser-déposer

Introduction.

J'espère que vous avez trouvé le tutoriel de la semaine dernière sur ImageCombo Control utile pour vos projets Microsoft Access. Avec le contrôle TreeView ImageCombo, nous pourrions créer un beau menu déroulant, avec plusieurs options, et l'adapter dans un petit espace sur le formulaire.

De même, dans une session précédente, nous avons appris à ajouter de nouveaux nœuds à un emplacement spécifique de la hiérarchie des nœuds ou à supprimer un nœud et à en ajouter un nouveau pour déplacer un nœud sur le contrôle de l'arborescence.

Cette méthode demande la création d'un nouvel enregistrement dans la table source pour le nouveau nœud. Ou supprimez un enregistrement existant et créez-en un nouveau pour déplacer un nœud existant afin de le rendre permanent. D'une certaine manière, avec l'utilisation des fonctions Ajouter/Supprimer, nous pourrions ajouter de nouveaux nœuds ou réorganiser les nœuds existants sur le contrôle TreeView. En ce qui concerne la réorganisation des nœuds, nous avons une meilleure façon de le faire, plutôt que de supprimer des nœuds et de les recréer. Faites glisser le nœud de son emplacement actuel et déposez-le là où nous voulons qu'il soit sur le contrôle TreeView. C'est ce que nous allons apprendre dans cet épisode

Cette approche simple ne nécessite que la mise à jour de la modification de la valeur du champ ParentID des enregistrements associés, pour rendre la modification permanente.

Les sujets abordés jusqu'à présent dans les sessions précédentes.

  1. Tutoriel sur le contrôle Microsoft TreeView
  2. Création d'un menu d'accès avec le contrôle TreeView
  3. Affectation d'images au contrôle TreeView
  4. Affectation d'images à TreeView Control-2
  5. TreeView Control-Mark Add Delete Nodes
  6. Menu déroulant d'accès TreeView ImageCombo

Mais, nous pouvons rencontrer des difficultés lors de l'utilisation de cette méthode et nous y reviendrons un peu plus tard dans cette session.

Tableau et formulaire de données de démonstration.

Nous avons besoin d'un tableau et d'un formulaire. Nous avons déjà une table appropriée avec le nom Échantillon créé lors d'une précédente session de didacticiel. Si vous avez déjà téléchargé la base de données de démonstration, à partir de la deuxième page de lien donnée ci-dessus, vous pouvez également utiliser cette base de données pour cette session. Nous utiliserons les objets suivants de cette base de données pour nos expériences de glisser-déposer :

  • Table :Exemple
  • Formulaire :frmSample

L'image de contrôle TreeView sur frmSample avec des données de démonstration est donnée ci-dessous à titre de référence :

Vous pouvez télécharger la base de données de démonstration (ProjectMenu.zip ) de la deuxième page de liens donnée ci-dessus et extrayez le ProjectMenu.accdb base de données.

Nouveau formulaire pour les essais de glisser-déposer.

  1. Ouvrez la base de données ProjectMenu.accdb.

  2. Faire une copie du tableau Exemple et nommez-le Sample_bk, gardez-le en sécurité, nous aurons besoin de ses données d'origine sans changement plus tard. Lorsque nous expérimentons la méthode glisser-déposer, il est nécessaire de mettre à jour la valeur du champ ParentId dans l'exemple de table de démonstration. Mais, nous avons besoin des données d'origine plus tard, sans ces modifications.

  3. Créez un nouveau formulaire avec le nom frmDragDrop .

  4. La conception de formulaire frmDragDrop ressemblera à l'image ci-dessous lorsque vous en aurez terminé.

  5. Insérez le contrôle TreeView de la liste des contrôles ActiveX et placez-le sur le formulaire, en laissant suffisamment d'espace au-dessus du contrôle, afin que nous puissions créer deux boutons de commande et une étiquette d'en-tête au-dessus. Faites glisser la poignée de redimensionnement dans le coin inférieur droit pour l'agrandir suffisamment pour afficher tous les nœuds, sans défilement.

  6. Modifier le Nom Valeur de propriété du contrôle TreeView sur TreeView0 .

  7. Insérez un bouton de commande au-dessus et à gauche du contrôle TreeView. Changer son Nom Valeur de la propriété à cmdExpand et Légende valeur pour Développer tout .

  8. Insérez un deuxième bouton de commande au-dessus et sur le bord droit du contrôle TreeView. Changer son Nom Valeur de la propriété à cmdCollapse et la Légende Valeur de la propriété pour Tout réduire.
  9. Insérez un contrôle d'étiquette au-dessus des boutons de commande, suffisamment large pour écrire le titre comme indiqué ci-dessus, et modifiez sa taille de police 14.

  10. Ignorez le contrôle ImageList, pour le moment, j'ai commenté les lignes de code qui modifient les numéros d'index Node ImageList. Plus tard, vous pouvez importer le contrôle ImageList avec des images téléchargées manuellement, à partir de notre ancienne base de données de démonstration de didacticiel (à partir de la 4ème page de liens donnée ci-dessus) et l'utiliser pour afficher des images de nœud sur des nœuds. Lorsque les positions des nœuds sont modifiées pendant les actions de glisser-déposer, nous devons également modifier les images de nœud en fonction de la position du nœud (nœud de niveau racine ou nœud enfant) sur le contrôle TreeView.

    Glisser-déposer le code du module de formulaire.

  11. Affichez le module de code VBA du formulaire frmDragDrop, copiez et collez le code VBA suivant (il ne s'agit que de la première moitié du code du module de formulaire) dans le module de classe du formulaire frmDragDrop et enregistrez le formulaire :

    Option Compare Database
    Option Explicit
    
    Dim tv As MSComctlLib.TreeView
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim imgListObj As MSComctlLib.ImageList
    Const KeyPrfx As String = "X"
    
    Private Sub Form_Open(Cancel As Integer)
    Set tv = Me.TreeView0.Object
    
    'Set imgListObj = Me.ImageList1.Object
    'tv.ImageList = imgListObj
    
    LoadTreeView
    
    End Sub
    
    Sub LoadTreeView()
    Dim strKey As String
    Dim strPKey As String
    Dim strText As String
    Dim strsQL As String
    
    strsQL = "SELECT * FROM Sample ORDER BY ID"
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strsQL, dbOpenDynaset)
        
    tv.Nodes.Clear
    
    'Add all Items are added as Root Nodes
    Do While Not rst.BOF And Not rst.EOF
        strKey = KeyPrfx & CStr(rst!ID)
        strText = rst!desc
        tv.Nodes.Add , , strKey, strText
        
        'With tv.Nodes.Item(strKey)
        '    .Image = 1
        '    .SelectedImage = 4
        'End With
    
        rst.MoveNext
    Loop
    
    'Prepare to update the Parent-Key of Nodes
    'wherever applicable to move and position the Child Nodes
    strPKey = ""
    rst.MoveFirst
    Do While Not rst.EOF
        strPKey = Nz(rst!parentid, "")
        
        If Len(strPKey) > 0 Then
            strPKey = KeyPrfx & strPKey
            strKey = KeyPrfx & CStr(rst!ID)
            strText = rst!desc
            
            'Move the Child Node under it's Parent-Node
            Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)
            
    'Update Image and SelectedImage Properties
    'with ImageList Index numbers
            'With tv.Nodes.Item(strKey)
            '    .Image = 2
            '    .SelectedImage = 3
            'End With
    
        End If
        rst.MoveNext
    Loop
    
    rst.Close
    Set rst = Nothing
    Set db = Nothing
    
    End Sub
    
    
    Private Sub TreeView0_NodeClick(ByVal Node As Object)
    Dim SelectionNode As MSComctlLib.Node
        
    'Ensure that the clicked node equals the selected node in the tree
    If Not Node Is Nothing Then
        Set SelectionNode = Node
           If SelectionNode.Expanded = True Then
                SelectionNode.Expanded = False
            Else
                SelectionNode.Expanded = True
            End If
    End If
    End Sub
    
    Private Sub cmdCollapse_Click()
    Dim tmpnod As MSComctlLib.Node
    For Each tmpnod In tv.Nodes
        If tmpnod.Expanded = True Then
            tmpnod.Expanded = False
        End If
    Next
    
    End Sub
    
    Private Sub cmdExpand_Click()
    Dim tmpnod As MSComctlLib.Node
    For Each tmpnod In tv.Nodes
        If tmpnod.Expanded = False Then
            tmpnod.Expanded = True
        End If
    Next
    
    End Sub

    Je sais que vous connaissez le code ci-dessus, si vous avez déjà parcouru les épisodes précédents, à l'exception de LoadTreeView() sous-programme avec quelques modifications. Ici, le remplissage des nœuds TreeView a été divisé en un processus en deux étapes.

    En bref, voici ce qui se passe dans ce sous-programme.

    • Tous les enregistrements sur Échantillon La table a été chargée en tant que nœuds de niveau racine du contrôle TreeView, avec une valeur de champ ID en tant que clé, dans la première étape.

    • Encore une fois, ces enregistrements ont été lus une seconde fois et recherchent une valeur dans le style Identifiant parent champ, s'il est vide, le nœud sera conservé en tant que nœud de niveau racine.

    • Si le champ ParentID a une valeur, identifiez le nœud avec la valeur ParentID comme Node-Key et déplacer le nœud actuel comme nœud enfant, ou son [Relative] Paramètre (de Ajouter () Méthode) la valeur est mise à jour.

    • Même s'il semble que la procédure de remplissage des nœuds en deux étapes soit un exercice inutile, il y a une bonne raison pour laquelle nous devons suivre cette méthode. Nous y reviendrons un peu plus tard et vous le saurez sans trop vous l'expliquer.

    • Sur la conception du formulaire, j'ai donné un contrôle ImageList. Vous pouvez insérer le Contrôle ActiveX ImageList et téléchargez manuellement certaines images à partir du disque, ou copiez et collez ce contrôle avec des images de téléchargements de base de données de démonstration antérieurs. Dans les deux cas, assurez-vous que le nom du contrôle ImageList est ImageList1 . Sinon, vous devez modifier le nom dans le code.

    • Après cela, activez les lignes commentées dans Form_Open() Event Procedure. Activez les lignes suivantes, en supprimant le symbole de commentaire au début de la ligne :

      'Set imgListObj = Me.ImageList1.Object
      'tv.ImageList = imgListObj
      

    • Dans le TreeView0_ OLEDragDrop() Le sous-programme (dans la 2ème partie du code VBA) active les paramètres d'index d'image des nœuds, en supprimant également les symboles de commentaire de ces lignes. Avec ces modifications, les images de nœud apparaîtront sur le contrôle TreeView. Si vous avez votre propre contrôle ImageList avec des images téléchargées, modifiez les numéros d'index en fonction de l'image que vous souhaitez insérer sur les nœuds.

      Le TreeView0_NodeClick() Procédure d'événement Développe le nœud actuel, si les nœuds enfants sont dans un état réduit, sinon, les nœuds enfants seront réduits. Normalement cette action est contrôlée (sans Code) en cliquant sur le +/- Symbole sur l'arborescence du nœud avec nœuds enfants.

      Les sous-routines cmdExpand_Click() et cmdCollapse_Click() Événements Développe tous les nœuds et réduit tous les nœuds respectivement.

      Lorsque le code ci-dessus s'exécute, l'affichage ressemble à l'image de la vue du formulaire ci-dessous :

    • Vous pouvez enregistrer le frmDragDrop Formez et ouvrez-le en mode Normal. Si tout s'est bien passé, vous verrez l'écran ci-dessus. Essayez l'option Tout développer et Tout réduire Boutons de commande et vérifiez s'ils fonctionnent également. Si ce n'est pas le cas, revérifiez que les paramètres suivants sont corrects ou non :

    • i) Le nom du contrôle TreeView est :TreeView0

    • ii) Afficher la feuille de propriétés de Exampand All Bouton de commande et sélectionnez [Procédure d'événement] dans Sur clic Propriété de l'événement.

    • iii) Assurez-vous que le même paramètre est intact pour Tout réduire Bouton de commande également.

    • iv) Cliquez sur un nœud, ayant des nœuds enfants, pour voir s'ils se replient ou se développent lors de clics répétés.

    • v) Si le contrôle ImageList est placé sur le formulaire, son nom doit être ImageList1 .

      Passons à la deuxième partie du code VBA qui implémente les événements Drag-Drop.

    Deuxième moitié du code VBA.

  12. Copiez la deuxième partie suivante du code VBA, sur le module de formulaire frmDragDrop, qui implémente l'action glisser-déposer, et collez-la sous le code existant :

    Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long)
        Set Me.TreeView0.SelectedItem = Nothing
    End Sub
    
    
    Private Sub TreeView0_OLEDragOver(Data As Object, _
                                    Effect As Long, _
                                    Button As Integer, _
                                    Shift As Integer, _
                                    x As Single, _
                                    y As Single, _
                                    State As Integer)
        
        Dim SelectedNode As MSComctlLib.Node
        Dim nodOver As MSComctlLib.Node
        
        If tv.SelectedItem Is Nothing Then
            'Select a node if one is not selected
            Set SelectedNode = tv.HitTest(x, y)
            If Not SelectedNode Is Nothing Then
                SelectedNode.Selected = True
            End If
        Else
            If tv.HitTest(x, y) Is Nothing Then
            'do nothing
            Else
                'Highlight the node the mouse is over
                Set nodOver = tv.HitTest(x, y)
                Set tv.DropHighlight = nodOver
            End If
        End If
    
    End Sub
    
    
    Private Sub TreeView0_OLEDragDrop(Data As Object, _
                                        Effect As Long, _
                                        Button As Integer, _
                                        Shift As Integer, _
                                        x As Single, _
                                        y As Single)
    
        Dim sourceNode As MSComctlLib.Node
        Dim SourceParentNode As MSComctlLib.Node
        Dim targetNode As MSComctlLib.Node
        
        Dim tmpRootNode As MSComctlLib.Node
        Dim strtmpNodKey As String
        Dim ChildNode As MSComctlLib.Node
        
        Dim strSPKey As String
        Dim strTargetKey As String
        
        Dim strsQL As String
        Dim intKey As Integer
        Dim intPKey As Integer
        
        On Error Resume Next
        
        Select Case Screen.ActiveControl.Name
                
               Case TreeView0.Name
                    Set sourceNode = tv.SelectedItem
                
        End Select
        
        'Get Source Parent Node & Target Node Reference
        Set SourceParentNode = sourceNode.Parent
        Set targetNode = tv.HitTest(x, y)
                
        'If any errors then exit
        If Err <> 0 Then
            MsgBox Err & " : " & Err.Description, vbInformation + vbCritical, "OLEDragDrop()"
            Err.Clear
            Exit Sub
        Else
            On Error GoTo 0
        End If
        
    
        'Get/define Source parent Node Key to compare it with Target Node Key
        If SourceParentNode Is Nothing Then
            strSPKey = "Empty"
        Else
            strSPKey = SourceParentNode.Key
        End If
        
        'Check the Target Node/Location and define the Key
         Select Case True
            Case targetNode Is Nothing
                strTargetKey = "Empty"
            
            Case targetNode.Key = ""
                strTargetKey = "Empty"
                Set targetNode = Nothing
            Case Else
                strTargetKey = targetNode.Key
         End Select
        
        'Make sure the Target Node is not the source Node's own parent
        If strTargetKey = strSPKey Then Exit Sub
        
        'Track User's Node move action, check for error.
        On Error Resume Next
        
        If targetNode Is Nothing Then
            
            'If target Node is Nothing (the Node dropped in the empty area),
            'then the Node must be moved to the Root-level
            'save the original sourceNode.Key
            strtmpNodKey = sourceNode.Key
            
            'Modify the source Node Key, with addition of some text, say 'Empty', like 'X5Empty'
            'So that a temporary Node can be created with the original source Node key.
            'Note: Two Nodes with the same Key cannot remain in memory at the same time.
            'The Source Node with key 'X5Empty' deleted later,
            'temporary Node takes it's droped location.
            sourceNode.Key = sourceNode.Key & strTargetKey
    
            'Create the temporary Root Node, with original sourceNode Key
            Set tmpRootNode = tv.Nodes.Add(, , strtmpNodKey, sourceNode.Text)
            
            'define the Root Node image indexes
            'With tmpRootNode
            '    .Image = 1
            '    .SelectedImage = 4
            'End With
            
            'Move all child Nodes from SourceNode,if any,
            'as tmpRootNode's Children
            Do Until sourceNode.Children = 0
                Set sourceNode.Child.Parent = tmpRootNode
                
                'modify Node image indexes
                'With sourceNode
                '    .Image = 2
                '    .SelectedImage = 3
                'End With
            Loop
    
            'Delete the Source Node with modified Key from TreeView
            tv.Nodes.Remove sourceNode.Index
            
            'Move the tmpRootNode with original Key
            'to the dropped location on TreeView
            Set sourceNode = tmpRootNode
        Else
            'Move the sourceNode under targetNode as child
            Set sourceNode.Parent = targetNode
            
            'modify Node image indexes
            'With sourceNode
            '    .Image = 2
            '    .SelectedImage = 3
            'End With
        End If
        
        'Notify, if there was an Error then Exit, else Update PrentID of related Record.
        If Err <> 0 Then
            MsgBox Err & " : " & "Unable to move:" & vbCrLf & Err.Description, vbInformation + vbCritical, "DragDrop2()"
            Exit Sub
        Else
            'Build and execute the SQL statement to update the record
            If targetNode Is Nothing Then
                intKey = Val(Mid(sourceNode.Key, 2))
                strsQL = "UPDATE Sample SET ParentID = Null" & _
                         " WHERE ID = " & intKey
            Else
                intKey = Val(Mid(sourceNode.Key, 2))
                intPKey = Val(Mid(targetNode.Key, 2))
                
                strsQL = "UPDATE sample SET ParentID = " & intPKey & _
                         " WHERE ID = " & intKey
            End If
            
            'Modify the table records
            CurrentDb.Execute strsQL, dbFailOnError
            
            'If an error raised then refresh TreeView and exit
            If Err <> 0 Then
                MsgBox Err & " : " & Err.Description
                LoadTreeView 'Refresh/display TreeView without changes
            Else
                'Sort Nodes
                If sourceNode.Parent Is Nothing Then
                    sourceNode.Root.Sorted = True
                Else
                    sourceNode.Parent.Sorted = True
                End If
                
                tv.Nodes(sourceNode.Key).Selected = True
            End If
        End If
        On Error GoTo 0
    
    End Sub
    
    Private Sub TreeView0_OLECompleteDrag(Effect As Long)
    
        'Turn off the drophighlight
        Set tv.DropHighlight = Nothing
    
    End Sub
    
    Private Sub Form_Close()
    
    Set tv = Nothing
    End Sub

Pour l'action Glisser-Déposer, il y a quatre sous-routines, elles s'exécutent automatiquement lorsque vous faites glisser le(s) nœud(s), mettez en surbrillance le nœud lorsqu'il est déplacé sur d'autres nœuds, et enfin le déposez sur un autre nœud ou sur la zone vide au niveau de la racine .

Les principales sous-routines du code.

  • TreeView0_OLEStartDrag() - Initialise l'élément sélectionné et définit le nœud sur Rien
  • TreeView0_OLEDragOver() - Fonctionne comme l'événement de déplacement de la souris, met en surbrillance le nœud, lorsqu'il fait glisser un nœud au-dessus, sur le chemin du nœud cible.
  • TreeView0_OLEDragDrop() – Effectue des vérifications et des contrôles, positionne le ou les nœuds dans l'emplacement déposé et met à jour l'enregistrement sur la table de base.
  • TreeView0_OLECompleteDrag() - La propriété DropHighlight est définie sur Nothing.

Nous pouvons faire le glisser-déposer fonctionne avec le TreeView0_OLEDragDrop() Sous-programme seul. Dans ce cas, il n'y aura pas de surbrillance de nœud, lorsque le nœud source se déplace sur d'autres nœuds, d'un emplacement à l'autre, sauf que le pointeur de la souris change pour faire glisser une deuxième flèche derrière lui, comme dans l'exemple d'image ci-dessous. :

Nous allons donc prêter attention à ce sous-programme et vérifier le code en détail depuis le début. Au début de la sous-routine, nous avons déclaré les nœuds et les variables de chaîne nécessaires, et d'autres.

Au lieu de répéter ici des analyses ligne par ligne, j'ai commenté chaque ligne/section de codes de manière appropriée afin que vous compreniez ce qu'elle fait lorsque vous parcourez le Code. Vous pouvez les parcourir.

La séquence des événements Drap Drop

Comprenons la séquence des événements, l'utilisateur sélectionne un nœud, traîne sur d'autres nœuds sur le chemin de sa destination finale, et lâche sur le nœud cible. Ou déposez-le sur la zone vide du contrôle TreeView, pour en faire un nœud de niveau racine.

Lorsque vous faites glisser un nœud sur un autre nœud-texte, le nœud-texte est mis en surbrillance, indiquant que votre position actuelle est sur ce nœud sur le chemin, où que vous alliez à partir d'ici. Lorsqu'il est déplacé hors du texte du nœud, la surbrillance disparaît. Cela se produit tout au long du nœud cible. Le TreeView0_OLEDragOver() La sous-routine s'occupe de cette action de mise en évidence.

Lorsque vous déposez un nœud quelque part, le TreeView0_OLEDragDrop() Le sous-programme prend la surcharge. Ici, nous devons analyser les intentions de l'utilisateur et prendre les mesures appropriées. Les informations suivantes doivent être enregistrées et analysées pour déplacer le nœud vers l'emplacement correct.

Les informations importantes à suivre.

  1. La référence du nœud source, les valeurs de la clé du nœud et de l'ID parent, les enfants du nœud, le cas échéant.

  2. Le nœud cible ou la référence d'emplacement, la clé de nœud.

  3. Si la cible n'est pas un nœud mais la zone vide du contrôle TreeView, alors le nœud source doit être déplacé vers la position de niveau racine.

  4. Le nœud source lorsqu'il est déposé sur un autre nœud, le nœud cible devient le nouveau parent du nœud source.

  5. Si le nœud source a ses propres enfants, ils doivent également être déplacés avec leur parent.

  6. ** Lorsque le nœud est glissé et déposé sur son propre nœud parent, ignorez cette action.

    ** Par exemple, vérifiez l'image ci-dessus. Si nous faisons glisser le TextBox Node et déposez-le dans son nœud parent Controls, ou fait glisser les Contrôles Node et déposez-le sur son nœud parent Form alors ces mouvements seront ignorés.

  7. ** Si niveau racine Le nœud est glissé et déposé dans la zone vide, aucune action ne sera entreprise car il s'agit déjà d'un nœud de niveau racine.

Pour tous les déplacements valides de Node, nous devons mettre à jour le ParentID valeur du champ de l'enregistrement associé sur l'échantillon Tableau.

Nœud Drop dans la zone vide au niveau de la racine.

Dans le cas de l'article numéro 3 ci-dessus, nous devons créer un nœud de niveau racine, avec le même numéro d'identification du nœud source, ce qui n'est pas autorisé. La valeur de clé en double n'est pas autorisée dans la hiérarchie TreeView. C'est le seul domaine du Code, où vous trouverez un peu de confusion sur la procédure qui y est suivie.

La procédure est la suivante :

  1. Modifiez la clé de nœud TreeView existante en ajoutant du texte supplémentaire (par exemple, clé X5 modifier à X5Empty ), pour éviter les conflits de clé, lors de la création d'un nœud temporaire avec la clé d'origine.

  2. Créer un temporaire Nœud avec la clé d'origine :X5.

  3. Déplacez tous les nœuds enfants du nœud source, le cas échéant, en tant que nœuds enfants vers le nœud temporaire.

  4. Supprimez le nœud source TreeView avec la clé modifiée :X5Empty depuis le contrôle TreeView, mais l'enregistrement associé dans la table Sample n'est pas touché.

  5. Déplacez le temporaire Nœud avec la clé d'origine X5 avec ses enfants à la position de niveau racine du contrôle TreeView.

  6. Mettez à jour le champ ParentID de l'enregistrement associé avec une chaîne de longueur nulle ("") pour le marquer en tant que nœud de niveau racine.

Expériences personnelles de glisser-déposer.

Vous pouvez essayer vous-même certaines expériences de glisser-déposer et voir comment cela fonctionne. Sélectionnez un nœud, cliquez et maintenez le bouton gauche de la souris, faites glisser le nœud et déposez-le sur un autre nœud, ou déposez-le dans une zone vide du contrôle TreeView. Lorsque vous faites glisser le nœud sur un autre texte de nœud, il est mis en surbrillance et lorsque vous êtes hors du nœud, la surbrillance s'éteint. Le nœud déplacé apparaîtra au nouvel emplacement où vous l'avez déposé. Vous pouvez répéter cette expérience de glisser-déposer en sélectionnant un seul nœud ou un nœud avec des enfants.

En fonction de ce mouvement de nœuds, l'ID parent de l'enregistrement associé la valeur du champ sera mise à jour avec la clé valeur (ID) de l'enregistrement lié au nœud cible.

Pourquoi une procédure de remplissage de nœud en deux étapes ?

Maintenant, nous allons revenir à LoadTreeView() Sous-programme, pour jeter un second regard sur le processus en deux étapes que nous avons adopté pour remplir tous les nœuds du contrôle TreeView.

  • Tous les enregistrements de l'exemple Les tables sont initialement ajoutées en tant que nœuds de niveau racine, en utilisant la valeur du champ ID comme clé de nœud.

  • Lors de la deuxième passe des enregistrements, si la valeur du champ ParentID est vide, ce nœud restera en tant que nœud de niveau racine, sans changement.

  • Tous les autres enregistrements liés aux nœuds avec la valeur ParentID sont correctement déplacés sous son nœud parent.

Naturellement, la question se pose, pourquoi devons-nous procéder ainsi ?

Nous allons faire une expérience simple pour rendre la réponse claire sans l'expliquer en trop de mots. Vous avez peut-être déjà effectué vous-même des essais d'essais par glisser-déposer et réorganisé les nœuds, au cours du processus, mis à jour les valeurs ParentID de ces enregistrements avec le changement. Nous devons donc réinitialiser les valeurs d'enregistrement à leur état d'origine dans l'exemple Table, avant de commencer une nouvelle démo.

Nous avons déjà créé une copie de notre tableau Exemple plus tôt, avec le nom Sample_bk comme sauvegarde. Supprimer l'exemple Tableauz et faites une copie à partir de Sample_bk avec le nom d'origine :Sample .

Ouvrez la table et affichez les enregistrements et leurs valeurs de champ ParentID. L'exemple d'image du tableau est donné ci-dessous :

Les valeurs de champ d'identification sont des numéros automatiques et elles sont toutes dans un ordre séquentiel et toutes les valeurs d'identification sont uniques. La règle simple suivante régit l'ajout d'un nœud enfant au contrôle TreeView.

La règle du nœud enfant simple : L'identifiant parent champ Valeur (Clé-Parent ) dans un enregistrement s'attend à ce qu'un nœud parent existe déjà dans le contrôle TreeView, avec la même valeur que Node-Key (l'identifiant).

Vérifiez le troisième enregistrement à partir du haut, dans l'image du tableau ci-dessus. La valeur du champ ParentID est 2 et l'ID de l'enregistrement actuel est 3. Dans ce cas, l'enregistrement avec l'ID 2 sera ajouté au contrôle TreeView avant que nous essayions d'ajouter le troisième enregistrement au nœud. Les deux enregistrements ne sont pas nécessairement côte à côte. Vérifiez l'enregistrement avec le numéro d'identification 21, sa valeur de champ ParentID est 12, inférieure à la valeur d'identification des enregistrements actuels 21.

Dans les deux cas, lorsque le programme rencontre la valeur ParentID dans un enregistrement, il suppose que l'enregistrement avec la valeur ID égale à ParentID a déjà été ajouté en tant que nœud dans le contrôle TreeView lors du cycle précédent de remplissage des nœuds.

Justifier la procédure en deux étapes.

Essayons quelques essais Drag-Drop. Mais, avant cela, nous avons un formulaire avec le nom frmSample, qui nous avons utilisé dans la première session de tutoriel, et en cela nous avons chargé tous les nœuds TreeView en une seule fois. Oui, nous avons suivi la même méthode jusqu'à présent et nous avons besoin de changement à partir de maintenant. Mais avant cela, ouvrons l'ancien formulaire et voyons comment les nœuds apparaissent sur le formulaire.

  1. Ouvrez le formulaire frmSample pour voir à quoi ressemble l'affichage TreeView, avec les enregistrements de la table Sample, chargés à l'aide de l'ancienne règle.

  2. Si vous avez fini de visualiser les nœuds TreeView, fermez le formulaire.

  3. Maintenant, ouvrez le frmDragDrop Formulaire. Nous nous préparons à glisser-déposer un nœud.

  4. Sélectionnez le Nœud avec le Nœud-Texte Table, Cliquez et maintenez le bouton gauche de la souris, faites-le glisser et déposez-le sur le nœud, avec le formulaire de nœud-texte.

  5. Le tableau Nœud avec ses champs de nœud enfant immédiats et ses nœuds enfants sont déplacés en tant que nœuds enfants sous le formulaire Noeud.

  6. Fermer le formulaire frmDragDrop et ouvrez-le à nouveau. Les nœuds apparaîtront correctement, là où vous les avez déposés, comme l'image ci-dessous.

  7. Maintenant, fermez le formulaire frmDragDrop.

  8. Ouvrez le formulaire frmSample pour voir comment ce changement apparaît sur ce formulaire. Vous serez accueilli par un message d'erreur, Élément introuvable avec Numéro d'erreur :35601.

  9. Sélectionnez le bouton de commande de débogage pour accéder à la ligne de code en surbrillance, où l'erreur s'est produite.

  10. Pointez la souris sur nodKey Paramètre de la méthode Add(), il affiche X3, pointe la souris sur ParentKey paramètre et il affiche X7.

    En regardant ces deux valeurs de paramètre, nous pouvons supposer que nous sommes dans l'enregistrement avec la valeur d'ID 3 et que nous essayons de désigner ce nœud comme nœud enfant, à un autre nœud non encore renseigné dans le contrôle TreeView, avec la valeur d'ID 7.

  11. Appuyez sur F5 Clé pour faire apparaître à nouveau la même boîte de dialogue et cliquez sur Fin Bouton de commande pour arrêter le programme et afficher le formulaire dans la fenêtre de la base de données. Fermez le frmSample Form.

  12. Ouvrez l'exemple Tableau pour afficher la disposition des numéros ParentID, après notre action de glisser-déposer. Les enregistrements ressembleront à l'image ci-dessous et j'ai mis en surbrillance l'enregistrement qui a déclenché l'erreur avec la valeur ParentID 7 et montrant sa position d'enregistrement parent.

En suivant la procédure normale de remplissage du nœud précédent, nous sommes à la troisième position d'enregistrement. Depuis, les enregistrements ParentID valeur 7, le Nod avec ID valeur 7 doit être présent dans le contrôle TreeView. Le nœud avec la valeur d'ID 7 n'est pas encore rempli dans le contrôle TreeView, mais nous essayons de référencer le nœud inexistant et cela déclenche une erreur.

Même si vous triez les enregistrements dans l'ordre du champ ParentID, la nouvelle disposition des enregistrements ressemblera à l'image ci-dessous :

Maintenant, le nœud parent d'un autre enregistrement n'est pas dans la position attendue.

Par conséquent, dans ces circonstances, notre approche de chargement des nœuds TreeView en deux étapes fonctionne également pour les actions normales et après le glisser-déposer.

In the first step populate all records as Root-level Nodes in the TreeView Control using ID field value as Node-Key.

Now, all the Nodes of all records are available in the TreeView Control. It will be easy to move them around wherever we want. It doesn’t say any of the required Node doesn’t exist in the TreeView.

In the second pass on the same set of records, the records with empty ParentID field values are untouched and allowed to remain as Root-level Nodes. In other cases moves the Node as Child-Node under its Parent Node, by updating the [Relative] Parameter of the Node with the following Statement:

Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)

This is what we do through the second pass on the same set of records. You may do it by resetting the Record Pointer to the first record, by executing rst.MoveFirst before the Do . . . Loop, EOF conditions and rst.MoveNext to access each record as we normally do.

Second Step in Reverse Order.

Or you may do it in reverse order. After populating all records as Root-level Nodes the Record Pointer will be beyond the last record and on the EOF position. You may reset the record pointer to the last record, by executing rst.MoveLast before the Do . . . Loop BOF check, and execute rst.MovePrevious to access each record and move the Nodes correctly under its p arent Node. But, the Nodes may load slightly differently in the placement order of Nodes.

You may try this out yourself with the above-suggested change of Code and see the result.

Download Demo Database


  1. MS-Access Class Module and VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access Base Class and Derived Objects
  4. VBA Base Class and Derived Object-2
  5. Base Class and Derived Object Variants
  6. MS-Access Recordset and Class Module
  7. Access Class Module and Wrapper Classes
  8. Wrapper Class Functionality Transformation