Access
 sql >> Database >  >> RDS >> Access

Riorganizza i nodi TreeView trascinandoli

Introduzione.

Spero che tu abbia trovato il tutorial della scorsa settimana su ImageCombo Control utile per i tuoi progetti Microsoft Access. Con il controllo TreeView ImageCombo, potremmo creare un bellissimo menu a discesa, con diverse opzioni, e sistemarlo in un piccolo spazio sul modulo.

Allo stesso modo, in una sessione precedente, abbiamo appreso come aggiungere nuovi nodi in una posizione specifica nella gerarchia dei nodi o come eliminare un nodo e aggiungerne uno nuovo per riposizionare un nodo sul controllo della visualizzazione ad albero.

Questo metodo richiede la creazione di un nuovo record nella tabella di origine per il nuovo nodo. Oppure elimina un record esistente e creane uno nuovo per spostare un nodo esistente e renderlo permanente. In un certo senso, con l'uso delle funzioni Aggiungi/Cancella, potremmo aggiungere nuovi nodi o riorganizzare i nodi esistenti sul controllo TreeView. Per quanto riguarda la riorganizzazione dei nodi, abbiamo un modo migliore per farlo, piuttosto che eliminare i nodi e ricrearli. Trascina il nodo dalla sua posizione corrente e rilascialo dove vogliamo che sia sul controllo TreeView. Questo è ciò che impareremo in questo episodio

Questo semplice approccio richiede solo l'aggiornamento della modifica del valore del campo ParentID dei record correlati, per rendere permanente la modifica.

Gli argomenti trattati finora nelle sessioni precedenti.

  1. Esercitazione sul controllo di Microsoft TreeView
  2. Creazione del menu di accesso con il controllo TreeView
  3. Assegnazione di immagini al controllo TreeView
  4. Assegnazione di immagini a TreeView Control-2
  5. Segnale di spunta Controllo TreeView Aggiungi Elimina nodi
  6. Menu di accesso a discesa TreeView ImageCombo

Tuttavia, potremmo dover affrontare alcune sfide durante l'utilizzo di questo metodo e ci arriveremo poco più avanti in questa Sessione.

Tabella e modulo dati demo.

Abbiamo bisogno di una tabella e di un modulo. Abbiamo già una tabella adatta con il nome Campione creato in una precedente sessione tutorial. Se hai già scaricato il Database Demo, dalla seconda Pagina di collegamento sopra indicata in precedenza, puoi utilizzare quel Database anche per questa Sessione. Useremo i seguenti oggetti da quel database per i nostri esperimenti Drag-Drop:

  • Tabella:Campione
  • Modulo:frmSample

L'immagine di controllo TreeView su frmSample con dati demo è riportata di seguito come riferimento:

Puoi scaricare il database demo (ProjectMenu.zip ) dalla Second Link Page di cui sopra ed estrarre il ProjectMenu.accdb Banca dati.

Nuovo modulo per le prove di trascinamento della selezione.

  1. Apri il database ProjectMenu.accdb.

  2. Crea una copia della tabella Campione e denominalo come Sample_bk, tienilo al sicuro, avremo bisogno dei suoi dati originali senza modifiche in seguito. Quando sperimentiamo il metodo drag-drop è necessario aggiornare il valore del campo ParentId sulla tabella dimostrativa del campione. Ma abbiamo bisogno dei dati originali in un secondo momento, senza queste modifiche.

  3. Crea un nuovo modulo con il nome frmDragDrop .

  4. Il design del modulo frmDragDrop apparirà come l'immagine riportata di seguito al termine.

  5. Inserisci il controllo TreeView dall'elenco dei controlli ActiveX e posizionalo sul modulo, lasciando abbastanza spazio sopra il controllo, in modo da poter creare due pulsanti di comando e un'etichetta di intestazione sopra di esso. Trascina la maniglia di ridimensionamento nell'angolo in basso a destra per renderla abbastanza grande da visualizzare tutti i nodi, senza scorrere.

  6. Cambia il Nome Valore della proprietà di TreeView Control su TreeView0 .

  7. Inserire un pulsante di comando sopra e il bordo sinistro del controllo TreeView. Cambia il suo Nome Valore della proprietà su cmdExpand e Didascalia valore a Espandi tutto .

  8. Inserisci un secondo pulsante di comando sopra e sul bordo destro del controllo TreeView. Cambia il suo Nome Valore della proprietà su cmdCollapse e la Didascalia Valore della proprietà su Comprimi tutto.
  9. Inserisci un controllo etichetta sopra i pulsanti di comando, abbastanza largo da scrivere l'intestazione come mostrato sopra e cambia la dimensione del carattere 14.

  10. Ignora il controllo ImageList, per il momento ho commentato le righe di codice che modificano i numeri di indice di Node ImageList. Successivamente, puoi importare il controllo ImageList con immagini caricate manualmente, dal nostro precedente database demo Tutorial (dalla 4a pagina di collegamento indicata sopra) e utilizzarlo per visualizzare le immagini dei nodi sui nodi. Quando le posizioni dei nodi vengono modificate durante le azioni di trascinamento della selezione, è necessario modificare le immagini dei nodi anche in base alla posizione del nodo (nodo a livello di radice o nodo figlio) sul controllo TreeView.

    Codice modulo modulo trascinamento.

  11. Visualizza il modulo codice VBA del modulo frmDragDrop, copia e incolla il seguente codice VBA (questa è solo la prima metà del codice modulo modulo) nel modulo classe del modulo frmDragDrop e salva il modulo:

    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

    So che conosci il codice di cui sopra, se hai già esaminato gli episodi precedenti, ad eccezione di LoadTreeView() sottoprogramma con alcune modifiche. Qui, la compilazione dei nodi TreeView è stata suddivisa in un processo in due fasi.

    In breve, questo è ciò che accade in questa subroutine.

    • Tutti i record su Campione Le tabelle sono state caricate come nodi a livello radice di TreeView Control, con un valore di campo ID come chiave, nel primo passaggio.

    • Anche in questo caso, questi record sono stati letti una seconda volta e hanno verificato la presenza di un valore in ParentId campo, se vuoto, il nodo verrà mantenuto come nodo a livello di radice.

    • Se il campo ParentID ha un Valore, identifica il Nodo con il valore ParentID come Node-Key e sposta il nodo corrente come suo nodo figlio, o il suo [Relativo] Parametro (di Aggiungi () Metodo) il valore viene aggiornato.

    • Anche se sembra che la procedura di popolamento dei nodi in due passaggi sia un esercizio non necessario, c'è una buona ragione per cui dobbiamo seguire questo metodo. Torneremo su questo poco dopo e lo saprai senza molte spiegazioni.

    • Sulla progettazione del modulo, ho fornito un controllo ImageList. Puoi inserire il controllo ActiveX ImageList e carica alcune immagini manualmente dal disco, oppure copia e incolla questo controllo con le immagini dei download di database demo precedenti. In entrambi i casi, assicurati che il nome del controllo ImageList sia ImageList1 . In caso contrario, è necessario modificare il nome nel codice.

    • Successivamente, abilita le righe commentate in Form_Open() Event Procedure. Abilita le seguenti righe, rimuovendo il simbolo del commento dall'inizio della riga:

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

    • Nella TreeView0_ OLEDragDrop() La subroutine (nella seconda parte del codice VBA) abilita i parametri dell'indice di immagine dei nodi, rimuovendo anche i simboli di commento da quelle righe. Con queste modifiche, le immagini del nodo appariranno sul controllo TreeView. Se disponi di un controllo ImageList con immagini caricate, modifica i numeri di indice in base all'immagine che desideri inserire nei nodi.

      Il TreeView0_NodeClick() Event Procedure Espande il nodo corrente, se i nodi figlio sono in uno stato compresso, altrimenti i nodi figlio verranno compressi. Normalmente questa azione è controllata (senza codice) cliccando su +/- Simbolo sulla linea ad albero del nodo con nodi figlio.

      Le subroutine cmdExpand_Click() e cmdCollapse_Click() Eventi Espande tutti i nodi e comprime tutti i nodi rispettivamente.

      Quando il codice sopra viene eseguito, il display appare come l'immagine di visualizzazione modulo fornita di seguito:

    • Puoi salvare il frmDragDrop Modulo e aprilo in Visualizzazione normale. Se tutto è andato bene, vedrai la schermata sopra. Prova Espandi tutto e Comprimi tutto Pulsanti di comando e controlla se funzionano anche loro. In caso contrario, ricontrolla che le seguenti impostazioni siano corrette o meno:

    • i) Il nome del controllo TreeView è:TreeView0

    • ii) Visualizza la scheda delle proprietà di Exampand All Pulsante di comando e seleziona [Procedura evento] in Al clic Proprietà dell'evento.

    • iii) Assicurati che la stessa impostazione sia intatta per Comprimi tutto Pulsante di comando anche.

    • iv) Fare clic su un nodo, con nodi figlio, per vedere se si comprimono o si espandono a clic ripetuti.

    • v) Se il controllo ImageList è inserito nel modulo, il suo nome deve essere ImageList1 .

      Procediamo con la seconda parte del Codice VBA che implementa gli eventi Drag-Drop.

    Seconda metà del codice VBA.

  12. Copia la seguente seconda parte del codice VBA, sul modulo modulo frmDragDrop, che implementa l'azione Drag-Drop, e incollalo sotto il codice esistente:

    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

Per l'azione Drag-Drop, ci sono quattro subroutine, che vengono eseguite automaticamente quando trascini i nodi, evidenzia il nodo quando viene spostato su altri nodi e infine lo rilascia su un nodo diverso o sull'area vuota a livello di radice .

Le principali subroutine del codice.

  • TreeView0_OLEStartDrag() - Inizializza l'elemento selezionato e imposta il Nodo su Niente
  • TreeView0_OLEDragOver() - Funziona come l'evento di spostamento del mouse, evidenzia il nodo, quando trascina un nodo sopra di esso, sulla strada per il nodo di destinazione.
  • TreeView0_OLEDragDrop() – Esegue controlli e controlli, posiziona i nodi nella posizione rilasciata e aggiorna il record sulla tabella di base.
  • TreeView0_OLECompleteDrag() - La proprietà DropHighlight è impostata su Nothing.

Possiamo eseguire i lavori di trascinamento della selezione con TreeView0_OLEDragDrop() Solo sottoprogramma. In tal caso, non ci sarà alcuna evidenziazione del nodo, quando il nodo sorgente si sposta su altri nodi, da una posizione all'altra, tranne per il fatto che il puntatore del mouse cambia trascinando una seconda freccia dietro di esso, come nell'immagine di esempio riportata di seguito :

Quindi, presteremo attenzione a questa subroutine e verificheremo il codice in dettaglio dall'inizio. All'inizio della subroutine, abbiamo dichiarato i Nodi e le Variabili String necessari e altri.

Invece di ripetere le analisi riga per riga qui, ho commentato opportunamente ogni riga/sezione di codice in modo che tu possa capire cosa fa quando esamini il codice. Puoi esaminarli.

La sequenza degli eventi Drap Drop

Cerchiamo di capire la sequenza di Eventi, l'Utente Seleziona un nodo, trascina su altri nodi sulla strada per la destinazione finale e rilascia sul nodo di destinazione. Oppure rilascialo nell'area vuota del controllo TreeView, per renderlo un nodo a livello di radice.

Quando trascini un Nodo su un altro Node-Text, il Node-Text viene evidenziato, dicendo che la tua posizione attuale è su questo Nodo in arrivo, ovunque tu stia andando da qui. Quando viene spostato fuori dal testo del nodo, l'evidenziazione scompare. Questo accade fino al nodo di destinazione. Il TreeView0_OLEDragOver() Subroutine si occupa di questa azione di evidenziazione.

Quando rilasci un nodo da qualche parte, TreeView0_OLEDragDrop() La subroutine viene sovraccaricata. Qui, dobbiamo analizzare le intenzioni dell'Utente e intraprendere le azioni appropriate. Le seguenti informazioni devono essere salvate e analizzate per spostare il Nodo nella posizione corretta.

Le informazioni importanti di cui tenere traccia.

  1. Il riferimento del nodo di origine, la chiave del nodo e i valori ParentID, i figli del nodo, se presenti.

  2. Il nodo di destinazione o il riferimento della posizione, la chiave del nodo.

  3. Se il Target non è un Nodo ma l'area vuota del Controllo TreeView, allora il Nodo Sorgente deve essere spostato nella posizione del livello principale.

  4. Il nodo di origine quando viene rilasciato su un altro nodo, il nodo di destinazione diventa il nuovo genitore del nodo di origine.

  5. Se Source Node ha i suoi figli, anche loro devono essere spostati con il loro genitore.

  6. ** Quando il nodo viene trascinato e rilasciato sul proprio nodo padre, ignora questa azione.

    ** Ad esempio, controlla l'immagine sopra. Se trasciniamo il Casella di testo Node e rilascialo nei Controlli del nodo principale o trascina i Controlli Node e rilascialo nel Modulo del nodo padre quindi quelle mosse verranno ignorate.

  7. ** Se a livello di radice Il nodo viene trascinato e rilasciato nell'area vuota, quindi non verrà eseguita alcuna azione perché è già un nodo a livello di radice.

Per tutte le mosse valide di Node, è necessario aggiornare il ParentID valore del campo del record correlato nel campione Tabella.

Rilascio del nodo nell'area vuota a livello di radice.

Nel caso dell'articolo numero 3 sopra, dobbiamo creare un Nodo a livello di Root, con lo stesso ID Number del Nodo Sorgente, che non è consentito. Il valore chiave duplicato non è consentito nella gerarchia TreeView. Questa è l'unica area del Codice, dove troverai un po' di confusione sulla procedura seguita lì.

La procedura è la seguente:

  1. Modifica la chiave del nodo TreeView esistente con l'aggiunta di del testo aggiuntivo (ad esempio Chiave X5 cambia a X5Vuoto ), per evitare conflitti di chiavi, durante la creazione di un nodo temporaneo con la chiave originale.

  2. Crea un temporaneo Nodo con la chiave originale:X5.

  3. Sposta tutti i nodi figlio dal nodo di origine, se presente, come nodi figlio al nodo temporaneo.

  4. Elimina il nodo sorgente TreeView con la chiave modificata:X5Empty dal controllo TreeView, ma il record relativo sulla tabella Campione non viene toccato.

  5. Sposta il temporaneo Nodo con la chiave originale X5 con i suoi figli alla posizione a livello di radice del controllo TreeView.

  6. Aggiorna il campo ParentID del record correlato con una stringa di lunghezza zero ("") per contrassegnarlo come nodo a livello di radice.

Esperimenti personali di trascinamento della selezione.

Puoi provare tu stesso alcuni esperimenti Drag and Drop e vedere come funziona. Selezionare un nodo, fare clic e tenere premuto il pulsante sinistro del mouse, trascinare il nodo e rilasciarlo su un altro nodo, oppure rilasciarlo in un'area vuota del controllo TreeView. Quando trascini il Nodo su un altro Node-Text viene evidenziato e quando sei fuori dal Node l'evidenziazione scompare. Il nodo trascinato apparirà nella nuova posizione in cui lo hai rilasciato. Puoi ripetere questo esperimento di trascinamento selezionando un singolo nodo o un nodo con figli.

Sulla base di questo movimento di nodi, il ParentID del record correlato il valore del campo verrà aggiornato con la Chiave valore (ID) del record relativo al nodo di destinazione.

Perché la procedura di popolamento dei nodi in due passaggi?

Ora torneremo a LoadTreeView() Subroutine, per dare una seconda occhiata al processo in due fasi che abbiamo adottato per popolare tutti i nodi nel controllo TreeView.

  • Tutti i record nel campione Le tabelle vengono inizialmente aggiunte come nodi a livello di radice, utilizzando il valore del campo ID come chiave di nodo.

  • Nel secondo passaggio dei record, se il valore del campo ParentID è vuoto, quel Nodo rimarrà come Nodo a livello di radice, senza modifiche.

  • Tutti gli altri record relativi ai nodi con ParentID Value vengono spostati correttamente sotto il relativo nodo padre.

Naturalmente, sorge la domanda, perché dobbiamo farlo in questo modo?

Faremo un semplice esperimento per chiarire la risposta senza spiegarla in troppe parole. Potresti aver già eseguito alcune esecuzioni di prova di trascinamento della selezione e riorganizzato i nodi, nel processo ha aggiornato i valori ParentID di quel record con la modifica. Quindi, dobbiamo ripristinare i valori del record al loro stato originale nel campione Table, prima di iniziare una nuova demo.

Abbiamo già creato una copia della nostra tabella Campione in precedenza, con il nome Sample_bk come backup. Elimina il campione Tabella ed esegui una copia da Sample_bk con il nome originale:Campione .

Aprire la tabella e visualizzare i record e i relativi valori del campo ParentID. L'immagine di esempio della tabella è riportata di seguito:

I valori del campo ID sono numeri automatici e sono tutti in ordine sequenziale e tutti i valori ID sono univoci. La seguente semplice regola regola l'aggiunta di un nodo figlio al controllo TreeView.

La regola del nodo figlio semplice: Il ID genitore campo Valore (Chiave principale ) in un record prevede che esista già un nodo padre nel controllo TreeView, con lo stesso valore di Node-Key (l'ID).

Controlla il terzo record dall'alto, nell'immagine della tabella sopra. Il valore del campo ParentID è 2 e l'ID del record corrente è 3. In questo caso, il record con ID 2 verrà aggiunto al controllo TreeView prima di tentare di aggiungere il terzo record al nodo. Entrambi i record non sono necessariamente uno accanto all'altro. Controlla il record con il numero ID 21, il suo valore del campo ParentID è 12, inferiore al valore ID del record corrente 21.

In entrambi i casi, quando il programma incontra il valore ParentID in un record, presuppone che il record con il valore ID uguale a ParentID sia stato già aggiunto come nodo nel controllo TreeView nel precedente ciclo di popolamento dei nodi.

Giustificare la procedura in due passaggi.

Proviamo alcune prove di Drag-Drop. Ma prima abbiamo un modulo con il nome frmSample, quale abbiamo usato nella prima Sessione del Tutorial, e in questo abbiamo caricato tutti i Nodi TreeView in una volta sola. Sì, finora abbiamo seguito lo stesso metodo e d'ora in poi abbiamo bisogno di alcuni cambiamenti. Ma prima apriamo il vecchio form e vediamo come appaiono i Nodi sul Form.

  1. Apri il modulo frmSample per vedere come appare la visualizzazione TreeView, con i record della tabella di esempio, caricati utilizzando la vecchia regola.

  2. Se hai finito di visualizzare i nodi TreeView, chiudi il modulo.

  3. Ora apri il frmDragDrop Modulo. Ci stiamo preparando a trascinare e rilasciare un nodo.

  4. Seleziona il Nodo con la Tabella Node-Text, Fai clic e tieni premuto il pulsante sinistro del mouse, trascinalo e rilascialo sul Nodo, con il Modulo Node-Text.

  5. La Tabella Nodo con i suoi Campi immediati del nodo figlio e i suoi nodi figlio vengono spostati come nodi figlio sotto il Modulo Nodo.

  6. Chiudi il modulo frmDragDrop e aprilo di nuovo. I nodi appariranno correttamente, dove li hai rilasciati, come nell'immagine riportata di seguito.

  7. Ora chiudi il modulo frmDragDrop.

  8. Apri il modulo frmSample per vedere come appare questa modifica su questo modulo. Verrai accolto con un messaggio di errore, Elemento non trovato con Numero errore:35601.

  9. Seleziona il pulsante di comando Debug per andare alla riga del codice evidenziata, dove si è verificato l'errore.

  10. Punta il mouse su nodKey Param del metodo Add(), mostra X3, punto il mouse su ParentKey parametro e mostra X7.

    Osservando questi due valori di parametro, possiamo presumere di essere nel record con il valore ID 3 e di provare a designare questo nodo come nodo figlio, per un altro nodo non ancora popolato nel controllo TreeView, con valore ID 7.

  11. Premi F5 Tasto per visualizzare di nuovo la stessa finestra di dialogo e fai clic su Fine Pulsante di comando per interrompere il programma e visualizzare il modulo nella finestra del database. Chiudi il modulo frmSample.

  12. Apri il campione Tabella per visualizzare la disposizione dei numeri ParentID, dopo la nostra azione di trascinamento della selezione. I record avranno l'aspetto dell'immagine riportata di seguito e ho evidenziato il record che ha attivato l'errore con valore ParentID 7 e mostrando la posizione del record principale.

Seguendo la precedente procedura normale di popolamento del nodo, siamo alla terza posizione del record. Dal momento che, il valore ParentID dei record 7, il Nod con ID valore 7 deve essere presente nel controllo TreeView. Il nodo con valore ID 7 non è ancora popolato nel controllo TreeView, ma stiamo cercando di fare riferimento al nodo inesistente e questo provoca un errore.

Anche se ordini i record nel campo ParentID, la nuova disposizione dei record sarà simile all'immagine riportata di seguito:

Ora, il nodo padre di un altro record non è nella posizione prevista.

Quindi, in queste circostanze, il nostro approccio di caricamento dei nodi TreeView in due fasi funziona sia per le azioni normali che dopo il trascinamento della selezione.

Nel primo passaggio, popola tutti i record come nodi a livello radice nel controllo TreeView utilizzando il valore del campo ID come chiave di nodo.

Ora, tutti i nodi di tutti i record sono disponibili nel controllo TreeView. Sarà facile spostarli dove vogliamo. Non dice che nessuno dei nodi richiesti non esiste in TreeView.

Nel secondo passaggio sullo stesso set di record, i record con valori di campo ParentID vuoti non vengono toccati e possono rimanere come nodi a livello radice. In altri casi sposta il nodo come nodo figlio sotto il suo nodo padre, aggiornando il [Relativo] Parametro del Nodo con la seguente Istruzione:

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 posizione. 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. Modulo di classe MS-Access e VBA
  2. Matrici di oggetti di classe VBA MS-Access
  3. Classe base MS-Access e oggetti derivati
  4. Classe base VBA e oggetto derivato-2
  5. Classe base e varianti di oggetti derivati
  6. Recordset MS-Access e modulo di classe
  7. Accedi al modulo di classe e alle classi wrapper
  8. Trasformazione della funzionalità della classe wrapper