Access
 sql >> Datenbank >  >> RDS >> Access

TreeView-Knoten per Drag and Drop neu anordnen

Einführung.

Ich hoffe, Sie fanden das Tutorial der letzten Woche zum ImageCombo-Steuerelement nützlich für Ihre Microsoft Access-Projekte. Mit dem TreeView ImageCombo Control konnten wir ein schönes Dropdown-Menü mit mehreren Optionen erstellen und es auf kleinem Raum im Formular unterbringen.

Ebenso haben wir in einer früheren Sitzung gelernt, wie man neue Knoten an einer bestimmten Position in der Knotenhierarchie hinzufügt oder einen Knoten löscht und einen neuen hinzufügt, um einen Knoten in der Baumansichtssteuerung zu verschieben.

Diese Methode fordert die Erstellung eines neuen Datensatzes in der Quellentabelle für den neuen Knoten an. Oder löschen Sie einen vorhandenen Datensatz und erstellen Sie einen neuen, um einen vorhandenen Knoten zu verschieben und ihn dauerhaft zu machen. In gewisser Weise könnten wir mit der Verwendung von Funktionen zum Hinzufügen/Löschen neue Knoten hinzufügen oder die vorhandenen Knoten auf dem TreeView-Steuerelement neu anordnen. Was das Neuanordnen von Knoten betrifft, haben wir einen besseren Weg, als Knoten zu löschen und neu zu erstellen. Ziehen Sie den Knoten von seiner aktuellen Position und legen Sie ihn an der gewünschten Stelle im TreeView-Steuerelement ab. Das werden wir in dieser Folge lernen

Bei diesem einfachen Ansatz muss lediglich die Änderung des ParentID-Feldwerts verwandter Datensätze aktualisiert werden, um die Änderung dauerhaft zu machen.

Die bisher in früheren Sitzungen behandelten Themen.

  1. Tutorial für das Microsoft TreeView-Steuerelement
  2. Zugriffsmenü mit TreeView-Steuerelement erstellen
  3. Bilder dem TreeView-Steuerelement zuweisen
  4. Zuweisen von Bildern zu TreeView Control-2
  5. TreeView Control-Häkchen hinzufügen Knoten löschen
  6. TreeView ImageCombo-Dropdown-Zugriffsmenü

Aber wir könnten bei der Anwendung dieser Methode auf einige Herausforderungen stoßen, und wir werden später in dieser Sitzung darauf zurückkommen.

Demo-Datentabelle und Formular.

Wir brauchen eine Tabelle und ein Formular. Wir haben bereits eine passende Tabelle mit dem Namen Sample in einer früheren Lernprogrammsitzung erstellt. Wenn Sie die Demo-Datenbank bereits von der oben angegebenen zweiten Link-Seite heruntergeladen haben, können Sie diese Datenbank auch für diese Sitzung verwenden. Wir werden die folgenden Objekte aus dieser Datenbank für unsere Drag-Drop-Experimente verwenden:

  • Tabelle:Beispiel
  • Formular:frmSample

Das TreeView Control Image auf frmSample mit Demodaten ist unten als Referenz angegeben:

Sie können die Demo-Datenbank herunterladen (ProjectMenu.zip ) von der oben angegebenen zweiten Link-Seite und extrahieren Sie die ProjectMenu.accdb Datenbank.

Neues Formular für Drag-Drop-Testläufe.

  1. Öffnen Sie die ProjectMenu.accdb-Datenbank.

  2. Erstellen Sie eine Kopie der Tabelle Beispiel und benennen Sie es als Sample_bk, Bewahren Sie es sicher auf, wir benötigen später seine unveränderten Originaldaten. Wenn wir mit der Drag-Drop-Methode experimentieren, ist es notwendig, den ParentId-Feldwert in der Sample-Demo-Tabelle zu aktualisieren. Aber wir brauchen später die Originaldaten ohne diese Änderungen.

  3. Erstellen Sie ein neues Formular mit dem Namen frmDragDrop .

  4. Das frmDragDrop-Formulardesign sieht aus wie das Bild unten, wenn Sie damit fertig sind.

  5. Fügen Sie das TreeView-Steuerelement aus der Liste der ActiveX-Steuerelemente ein und platzieren Sie es auf dem Formular, wobei Sie genügend Platz über dem Steuerelement lassen, damit wir zwei Befehlsschaltflächen und eine Überschriftenbeschriftung darüber erstellen können. Ziehen Sie den Größenziehpunkt in der unteren rechten Ecke, um ihn groß genug zu machen, um alle Knoten anzuzeigen, ohne zu scrollen.

  6. Ändern Sie den Namen Eigenschaftswert des TreeView-Steuerelements auf TreeView0 .

  7. Fügen Sie eine Befehlsschaltfläche oberhalb und am linken Rand des TreeView-Steuerelements ein. Ändern Sie seinen Namen Eigenschaftswert zu cmdExpand und Bildunterschrift Wert auf Alle erweitern .

  8. Fügen Sie eine zweite Befehlsschaltfläche über und am rechten Rand des TreeView-Steuerelements ein. Ändern Sie seinen Namen Eigenschaftswert auf cmdCollapse und die Bildunterschrift Eigenschaftswert auf Alle minimieren.
  9. Fügen Sie über den Befehlsschaltflächen ein Beschriftungssteuerelement ein, das breit genug ist, um die Überschrift wie oben gezeigt zu schreiben, und ändern Sie die Schriftgröße 14.

  10. Ignorieren Sie das ImageList-Steuerelement vorerst, ich habe die Codezeilen auskommentiert, die die Node ImageList-Indexnummern ändern. Später können Sie das ImageList-Steuerelement mit manuell hochgeladenen Bildern aus unserer früheren Tutorial-Demo-Datenbank (von der oben angegebenen 4. Link-Seite) importieren und es verwenden, um Node-Images auf Nodes anzuzeigen. Wenn Knotenpositionen während Drag-Drop-Aktionen geändert werden, müssen wir Knotenbilder auch in Abhängigkeit von der Position des Knotens (Root-Level-Knoten oder untergeordneter Knoten) im TreeView-Steuerelement ändern.

    Drag-Drop-Formularmodulcode.

  11. Zeigen Sie das VBA-Codemodul des Formulars frmDragDrop an, kopieren und fügen Sie den folgenden VBA-Code (dies ist nur die erste Hälfte des Formularmodulcodes) in das Klassenmodul des frmDragDrop-Formulars ein und speichern Sie das Formular:

    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

    Ich weiß, dass Sie mit dem obigen Code vertraut sind, wenn Sie bereits die früheren Episoden durchlaufen haben, mit Ausnahme von LoadTreeView() Unterprogramm mit einigen Änderungen. Hier wurde das Füllen der TreeView-Knoten in einen zweistufigen Prozess unterteilt.

    Kurz gesagt, das passiert in dieser Subroutine.

    • Alle Datensätze in Probe Die Tabelle wurde im ersten Schritt als Root-Level-Knoten des TreeView-Steuerelements mit einem ID-Feldwert als Schlüssel geladen.

    • Auch diese Datensätze wurden ein zweites Mal gelesen und auf einen Wert im Eltern-ID Wenn das Feld leer ist, wird der Knoten als Root-Level-Knoten beibehalten.

    • Wenn das ParentID-Feld einen Wert hat, dann identifizieren Sie den Knoten mit dem ParentID-Wert als Node-Key und Verschieben Sie den aktuellen Knoten als untergeordneten Knoten oder als [Relativ] Parameter (von Hinzufügen () Methode) Wert wird aktualisiert.

    • Auch wenn es den Anschein hat, dass die zweistufige Node-Füllprozedur eine unnötige Übung ist, gibt es einen guten Grund, warum wir dieser Methode folgen müssen. Wir werden etwas später darauf zurückkommen und Sie werden es ohne viel Erklären wissen.

    • Auf das Design des Formulars habe ich ein ImageList Control gegeben. Sie können das ImageList ActiveX Control einfügen und laden Sie einige Bilder darin manuell von der Festplatte hoch, oder kopieren Sie dieses Steuerelement und fügen Sie es mit Bildern aus früheren Demo-Datenbank-Downloads ein. Stellen Sie in jedem Fall sicher, dass der Name des ImageList-Steuerelements ImageList1 lautet . Andernfalls müssen Sie den Namen im Code ändern.

    • Aktivieren Sie danach die auskommentierten Zeilen in Form_Open() Event Procedure. Aktivieren Sie die folgenden Zeilen, indem Sie das Kommentarsymbol am Anfang der Zeile entfernen:

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

    • In TreeView0_ OLEDragDrop() Die Subroutine (im 2. Teil des VBA-Codes) aktiviert die Bildindexparameter von Knoten, indem auch die Kommentarsymbole aus diesen Zeilen entfernt werden. Mit diesen Änderungen werden die Knotenbilder auf dem TreeView-Steuerelement angezeigt. Wenn Sie ein eigenes ImageList-Steuerelement mit hochgeladenen Bildern haben, ändern Sie die Indexnummern basierend auf dem Bild, das Sie in die Knoten einfügen möchten.

      Der TreeView0_NodeClick() Ereignisprozedur Erweitert den aktuellen Knoten, wenn sich die untergeordneten Knoten in einem reduzierten Zustand befinden, andernfalls werden die untergeordneten Knoten reduziert. Normalerweise wird diese Aktion (ohne Code) durch Klicken auf das +/- gesteuert Symbol auf der Baumlinie des Knotens mit untergeordneten Knoten.

      Die Subroutinen cmdExpand_Click() und cmdCollapse_Click() Ereignisse Erweitert alle Knoten bzw. reduziert alle Knoten.

      Wenn der obige Code ausgeführt wird, sieht die Anzeige wie das unten angegebene Formularansichtsbild aus:

    • Sie können frmDragDrop speichern Formular und öffnen Sie es in der Normalansicht. Wenn alles gut gelaufen ist, sehen Sie den obigen Bildschirm. Probieren Sie Alle erweitern aus und Alle minimieren Befehlsschaltflächen und überprüfen Sie, ob sie auch funktionieren. Wenn nicht, überprüfen Sie erneut, ob die folgenden Einstellungen korrekt sind oder nicht:

    • i) Der Name des TreeView-Steuerelements lautet:TreeView0

    • ii) Zeigen Sie das Eigenschaftenblatt von Exampand All an Befehlsschaltfläche und wählen Sie [Ereignisprozedur] unter Bei Klick Ereigniseigenschaft.

    • iii) Stellen Sie sicher, dass die gleiche Einstellung für Alle reduzieren intakt ist Befehlsschaltfläche auch.

    • iv) Klicken Sie auf einen Knoten mit untergeordneten Knoten, um zu sehen, ob sie bei wiederholten Klicks reduziert oder erweitert werden.

    • v) Wenn das ImageList Control auf dem Formular platziert wird, muss sein Name ImageList1 lauten .

      Lassen Sie uns mit dem zweiten Teil des VBA-Codes fortfahren, der die Drag-Drop-Ereignisse implementiert.

    Zweite Hälfte des VBA-Codes.

  12. Kopieren Sie den folgenden zweiten Teil des VBA-Codes auf das frmDragDrop-Formularmodul, das die Drag-Drop-Aktion implementiert, und fügen Sie ihn unter dem vorhandenen Code ein:

    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

Für die Drag-Drop-Aktion gibt es vier Subroutinen, die automatisch ausgeführt werden, wenn Sie den/die Knoten ziehen, den Knoten hervorheben, wenn er über andere Knoten bewegt wird, und ihn schließlich auf einem anderen Knoten oder auf dem leeren Bereich der Stammebene ablegen .

Die wichtigsten Subroutinen des Codes.

  • TreeView0_OLEStartDrag() - Initialisiert das ausgewählte Element und setzt den Knoten auf Nichts
  • TreeView0_OLEDragOver() - Funktioniert wie das Mausbewegungsereignis, hebt den Knoten hervor, wenn ein Knoten darüber gezogen wird, auf dem Weg zum Zielknoten.
  • TreeView0_OLEDragDrop() – Führt Überprüfungen und Kontrollen durch, positioniert den/die Knoten an der abgelegten Position und aktualisiert den Datensatz in der Basistabelle.
  • TreeView0_OLECompleteDrag() - Die DropHighlight-Eigenschaft ist auf „Nichts“ gesetzt.

Wir können die Drag-and-Drop-Arbeiten mit TreeView0_OLEDragDrop() ausführen Unterprogramm allein. In diesem Fall wird es keine Knotenhervorhebung geben, wenn sich der Quellknoten über andere Knoten bewegt, von einer Position zur anderen, außer dass sich der Mauszeiger dahingehend ändert, einen zweiten Pfeil dahinter zu ziehen, wie im Beispielbild unten :

Also werden wir dieser Unterroutine Aufmerksamkeit schenken und den Code von Anfang an im Detail prüfen. Am Anfang der Subroutine haben wir die notwendigen Nodes und String-Variablen und andere deklariert.

Anstatt hier zeilenweise Analysen zu wiederholen, habe ich jede Zeile/jeden Abschnitt des Kodex angemessen kommentiert, damit Sie verstehen, was er bewirkt, wenn Sie den Kodex durchgehen. Sie können sie durchgehen.

Die Abfolge von Drap-Drop-Ereignissen

Lassen Sie uns die Abfolge von Ereignissen verstehen, die der Benutzer auswählt ein Knoten, wird auf dem Weg zu seinem endgültigen Ziel über andere Knoten gezogen und abgelegt es auf dem Zielknoten. Oder legen Sie es auf dem leeren Bereich des TreeView-Steuerelements ab, um es zu einem Root-Level-Knoten zu machen.

Wenn Sie einen Knoten über einen anderen Knotentext ziehen, wird der Knotentext hervorgehoben und sagt, dass Ihre aktuelle Position auf diesem Knoten unterwegs ist, wohin Sie von hier aus gehen. Beim Herausbewegen aus dem Knotentext verschwindet die Hervorhebung. Dies geschieht bis zum Zielknoten. Das TreeView0_OLEDragOver() Die Unterroutine kümmert sich um diese Hervorhebungsaktion.

Wenn Sie einen Knoten irgendwo ablegen, wird TreeView0_OLEDragDrop() Subroutine übernimmt Überladung. Hier müssen wir die Absichten des Nutzers analysieren und entsprechende Maßnahmen ergreifen. Die folgenden Informationen müssen gespeichert und analysiert werden, um den Knoten an die richtige Stelle zu verschieben.

Wichtige Informationen, die Sie im Auge behalten sollten.

  1. Die Quellenknotenreferenz, Knotenschlüssel- und ParentID-Werte, untergeordnete Knoten, falls vorhanden.

  2. Der Zielknoten oder Standortreferenz, Knotenschlüssel.

  3. Wenn das Ziel kein Knoten ist, sondern der leere Bereich des TreeView-Steuerelements, dann wird der Quellknoten an die Position auf der Wurzelebene verschoben.

  4. Wenn der Quellknoten auf einen anderen Knoten abgelegt wird, wird der Zielknoten zum neuen Elternknoten des Quellknotens.

  5. Wenn der Quellknoten seine eigenen untergeordneten Elemente hat, müssen diese ebenfalls mit ihrem übergeordneten Element verschoben werden.

  6. ** Wenn der Knoten auf seinen eigenen Elternknoten gezogen und dort abgelegt wird, ignorieren Sie diese Aktion.

    ** Überprüfen Sie zum Beispiel das obige Bild. Wenn wir die TextBox ziehen -Knoten und legen Sie ihn auf seinem übergeordneten Knoten Controls, ab oder ziehen Sie die Steuerung Knoten und legen Sie ihn auf seinem übergeordneten Formular ab dann werden diese Züge ignoriert.

  7. ** Wenn Stammebene Der Knoten wird per Drag &Drop in den leeren Bereich gezogen, dann wird keine Aktion ausgeführt, da es sich bereits um einen Root-Level-Knoten handelt.

Für alle gültigen Verschiebungen von Node müssen wir die ParentID aktualisieren Feldwert des zugehörigen Datensatzes in der Stichprobe Tabelle.

Knotenabwurf im leeren Bereich der Stammebene.

Bei Artikelnummer 3 oben müssen wir einen Root-Level-Knoten mit derselben ID-Nummer wie der Quellknoten erstellen, was nicht zulässig ist. Doppelte Schlüsselwerte sind in der TreeView-Hierarchie nicht zulässig. Dies ist der einzige Bereich des Kodex, in dem Sie das dort befolgte Verfahren etwas verwirrend finden werden.

Das Verfahren ist wie folgt:

  1. Ändern Sie den vorhandenen TreeView-Knotenschlüssel, indem Sie zusätzlichen Text hinzufügen (z. B. Schlüssel X5 ändern zu X5Empty ), um Schlüsselkonflikte zu vermeiden, während ein temporärer Knoten mit dem ursprünglichen Schlüssel erstellt wird.

  2. Erstellen Sie ein vorläufiges Knoten mit dem Originalschlüssel:X5.

  3. Verschieben Sie alle untergeordneten Knoten vom Quellknoten, falls vorhanden, als untergeordnete Knoten zum temporären Knoten.

  4. Löschen Sie den TreeView-Quellknoten mit dem geänderten Schlüssel:X5Empty aus dem TreeView-Steuerelement, aber der zugehörige Datensatz in der Probentabelle wird nicht berührt.

  5. Verschieben Sie das Provisorium Knoten mit dem Originalschlüssel X5 mit seinen untergeordneten Elementen an die Root-Level-Position des TreeView-Steuerelements.

  6. Aktualisieren Sie das ParentID-Feld des verknüpften Datensatzes mit einer Zeichenfolge der Länge Null („“), um es als Knoten auf Stammebene zu kennzeichnen.

Selbstexperimente von Drag Drop.

Sie können selbst einige Drag-and-Drop-Experimente ausprobieren und sehen, wie es funktioniert. Wählen Sie einen Knoten aus, klicken und halten Sie die linke Maustaste gedrückt, ziehen Sie den Knoten und legen Sie ihn auf einem anderen Knoten ab oder legen Sie ihn in einem leeren Bereich des TreeView-Steuerelements ab. Wenn Sie den Knoten über anderen Knotentext ziehen, wird er hervorgehoben, und wenn Sie den Knoten verlassen, erlischt die Hervorhebung. Der gezogene Knoten erscheint an der neuen Position, an der Sie ihn abgelegt haben. Sie können dieses Drag-Drop-Experiment wiederholen, indem Sie einen einzelnen Knoten oder Knoten mit untergeordneten Elementen auswählen.

Basierend auf dieser Bewegung von Knoten die ParentID des zugehörigen Datensatzes Feldwert wird mit dem Schlüssel aktualisiert Wert (ID) des auf den Zielknoten bezogenen Datensatzes.

Warum zweistufiges Verfahren zum Befüllen von Knoten?

Jetzt gehen wir zurück zu LoadTreeView() Unterroutine, um einen zweiten Blick auf den zweistufigen Prozess zu werfen, den wir zum Füllen aller Knoten für das TreeView-Steuerelement übernommen haben.

  • Alle Datensätze in der Stichprobe Tabellen werden zunächst als Root-Level-Knoten hinzugefügt, wobei der ID-Feldwert als Knotenschlüssel verwendet wird.

  • Wenn im zweiten Durchlauf der Aufzeichnungen der Wert des ParentID-Felds leer ist, bleibt dieser Knoten ohne Änderung ein Knoten auf Stammebene.

  • Alle anderen auf Knoten bezogenen Datensätze mit ParentID-Wert werden korrekt unter den übergeordneten Knoten verschoben.

Da stellt sich natürlich die Frage, warum wir das so machen müssen?

Wir werden ein einfaches Experiment durchführen, um die Antwort klar zu machen, ohne sie in zu vielen Worten zu erklären. Möglicherweise haben Sie selbst bereits einige Testläufe von Drag-and-Drop-Testläufen durchgeführt und Knoten neu angeordnet und dabei die ParentID-Werte dieser Datensätze mit der Änderung aktualisiert. Daher müssen wir die Datensatzwerte im Beispiel auf ihren ursprünglichen Zustand zurücksetzen Tabelle, bevor wir eine neue Demo starten.

Wir haben bereits eine Kopie unserer Tabelle Beispiel erstellt früher unter dem Namen Sample_bk als Backup. Löschen Sie das Beispiel Tabelle und Kopie von Sample_bk erstellen mit dem ursprünglichen Namen:Probe .

Öffnen Sie die Tabelle und sehen Sie sich die Datensätze und ihre ParentID-Feldwerte an. Das Beispielbild der Tabelle ist unten angegeben:

Die ID-Feldwerte sind AutoNumbers und sie sind alle in sequentieller Reihenfolge und alle ID-Werte sind eindeutig. Die folgende einfache Regel regelt das Hinzufügen eines untergeordneten Knotens zum TreeView-Steuerelement.

Die Regel für einfache untergeordnete Knoten: Die Eltern-ID Feld Wert (Parent-Key ) in einem Datensatz erwartet, dass im TreeView-Steuerelement bereits ein übergeordneter Knoten mit demselben Wert wie Node-Key vorhanden ist (die ID).

Überprüfen Sie den dritten Datensatz von oben im obigen Tabellenbild. Der Wert des ParentID-Felds ist 2 und die ID des aktuellen Datensatzes ist 3. In diesem Fall wird der Datensatz mit der ID 2 zum TreeView-Steuerelement hinzugefügt, bevor wir versuchen, den dritten Datensatz zum Knoten hinzuzufügen. Beide Platten müssen nicht unbedingt nebeneinander liegen. Überprüfen Sie den Datensatz mit der ID-Nummer 21, sein ParentID-Feldwert ist 12, kleiner als der aktuelle Datensatz-ID-Wert 21.

Wenn das Programm in jedem Fall auf den ParentID-Wert in einem Datensatz stößt, geht es davon aus, dass der Datensatz mit dem ID-Wert gleich der ParentID bereits als Knoten im TreeView-Steuerelement im früheren Zyklus des Auffüllens der Knoten hinzugefügt wurde.

Begründung des zweistufigen Verfahrens.

Lassen Sie uns einige Drag-Drop-Testläufe ausprobieren. Aber vorher haben wir ein Formular mit dem Namen frmSample, welche die wir in der ersten Tutorial-Sitzung verwendet haben, und in der wir alle TreeView-Knoten auf einmal geladen haben. Ja, wir sind bisher der gleichen Methode gefolgt, und wir brauchen von nun an etwas Änderung. Aber lassen Sie uns vorher das alte Formular öffnen und sehen, wie die Knoten auf dem Formular erscheinen.

  1. Öffnen Sie das Formular frmSample um zu sehen, wie die TreeView-Anzeige aussieht, mit den Datensätzen der Beispieltabelle, die nach der alten Regel geladen wurden.

  2. Wenn Sie mit dem Betrachten der TreeView-Knoten fertig sind, schließen Sie das Formular.

  3. Öffnen Sie nun das frmDragDrop Form. Wir bereiten das Ziehen und Ablegen eines Knotens vor.

  4. Wählen Sie den Knoten mit der Knotentext Tabelle, aus Klicken und halten Sie die linke Maustaste gedrückt, ziehen Sie sie auf den Knoten mit dem Knoten-Text-Formular.

  5. Die Tabelle Knoten mit seinem unmittelbar untergeordneten Knoten Fields und seine untergeordneten Knoten werden als untergeordnete Knoten unter das Formular verschoben Knoten.

  6. Schließen Sie das Formular frmDragDrop und öffne es wieder. Die Knoten werden dort korrekt angezeigt, wo Sie sie abgelegt haben, wie das Bild unten zeigt.

  7. Schließen Sie nun das Formular frmDragDrop.

  8. Öffnen Sie das Formular frmSample um zu sehen, wie diese Änderung auf diesem Formular erscheint. Sie werden mit einer Fehlermeldung begrüßt:Element nicht gefunden mit Fehlernummer:35601.

  9. Wählen Sie die Debug-Befehlsschaltfläche, um zur hervorgehobenen Codezeile zu gehen, in der der Fehler aufgetreten ist.

  10. Zeigen Sie mit der Maus auf den nodKey Param der Methode Add(), es zeigt X3, Punkt die Maus auf dem ParentKey Parameter und es zeigt X7.

    Wenn wir uns diese beiden Parameterwerte ansehen, können wir davon ausgehen, dass wir uns auf dem Datensatz mit dem ID-Wert 3 befinden und versuchen, diesen Knoten als untergeordneten Knoten für einen anderen Knoten festzulegen, der noch nicht in das TreeView-Steuerelement mit dem ID-Wert 7 eingefügt wurde.

  11. Drücken Sie F5 Drücken Sie die Taste , um dasselbe Dialogfeld erneut aufzurufen, und klicken Sie auf Ende Befehlsschaltfläche, um das Programm zu stoppen und das Formular im Datenbankfenster aufzurufen. Schließen Sie das frmSample-Formular.

  12. Öffnen Sie das Beispiel Tabelle, um die Anordnung der ParentID-Nummern nach unserer Drag-and-Drop-Aktion anzuzeigen. Die Datensätze sehen wie das unten angegebene Bild aus und ich habe den Datensatz hervorgehoben, der den Fehler mit dem ParentID-Wert 7 ausgelöst hat und zeigt die Position des übergeordneten Datensatzes.

Nach der früheren Node-Population-Normalprozedur befinden wir uns an der dritten Datensatzposition. Da die ParentID den Wert 7 aufzeichnet, weist Nod den ID-Wert 7 auf muss im TreeView Control vorhanden sein. Der Knoten mit dem ID-Wert 7 ist noch nicht in das TreeView-Steuerelement gefüllt, aber wir versuchen, auf den nicht vorhandenen Knoten zu verweisen, und dies löst einen Fehler aus.

Selbst wenn Sie die Datensätze in der Reihenfolge des ParentID-Feldes sortieren, sieht die neue Anordnung der Datensätze wie im folgenden Bild aus:

Jetzt befindet sich der übergeordnete Knoten eines anderen Datensatzes nicht an der erwarteten Position.

Daher funktioniert unser zweistufiger Ansatz zum Laden von TreeView-Knoten unter diesen Umständen sowohl für normale als auch für Aktionen nach dem Ziehen und Ablegen.

Füllen Sie im ersten Schritt alle Datensätze als Root-Level-Knoten im TreeView-Steuerelement mit dem ID-Feldwert als Node-Key.

Jetzt sind alle Knoten aller Datensätze im TreeView Control verfügbar. Es wird einfach sein, sie überall hin zu bewegen, wo wir wollen. Es heißt nicht, dass einer der erforderlichen Knoten in der TreeView nicht vorhanden ist.

Beim zweiten Durchlauf desselben Satzes von Datensätzen bleiben die Datensätze mit leeren ParentID-Feldwerten unberührt und können als Knoten auf Stammebene verbleiben. In anderen Fällen wird der Knoten als untergeordneter Knoten unter seinen übergeordneten Knoten verschoben, indem der [Relative] aktualisiert wird Parameter des Knotens mit folgender Anweisung:

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-Klassenmodul und VBA
  2. MS-Access-VBA-Klassenobjekt-Arrays
  3. MS-Access-Basisklasse und abgeleitete Objekte
  4. VBA Base Class and Derived Object-2
  5. Basisklasse und abgeleitete Objektvarianten
  6. MS-Access Recordset and Class Module
  7. Zugriff auf Klassenmodul und Wrapper-Klassen
  8. Umwandlung der Wrapper-Klassenfunktionalität