sql >> Databasteknik >  >> RDS >> Access

Ordna om TreeView-noder genom att dra och släppa

Introduktion.

Jag hoppas att du tyckte att förra veckans handledning om ImageCombo Control var användbar för dina Microsoft Access-projekt. Med TreeView ImageCombo Control kan vi skapa en vacker rullgardinsmeny, med flera alternativ, och rymma den i ett litet utrymme på formuläret.

På samma sätt har vi i en tidigare session lärt oss hur man lägger till nya noder på en specifik plats i nodhierarkin eller tar bort en nod och lägger till en ny för att flytta en nod på trädvykontrollen.

Denna metod kräver skapandet av en ny post i källtabellen för den nya noden. Eller ta bort en befintlig post och skapa en ny för att flytta en befintlig nod för att göra den permanent. På ett sätt, med hjälp av Lägg till/Ta bort funktioner, kan vi lägga till nya noder eller arrangera om de befintliga noderna på TreeView-kontrollen. När det gäller omarrangering av noder har vi ett bättre sätt att göra det, snarare än att ta bort noder och återskapa dem. Dra noden från dess nuvarande plats och släpp den där vi vill att den ska vara på TreeView-kontrollen. Det här är vad vi ska lära oss i det här avsnittet

Denna enkla metod behöver bara uppdatera ändringen av ParentID-fältvärdet för relaterade poster, för att göra ändringen permanent.

Ämnen som behandlats hittills under tidigare sessioner.

  1. Microsoft TreeView Control Tutorial
  2. Skapa åtkomstmeny med TreeView-kontroll
  3. Tilldela bilder till TreeView-kontroll
  4. Tilldela bilder till TreeView Control-2
  5. TreeView Control Markera Lägg till Ta bort noder
  6. TreeView ImageCombo Rullgardinsmeny för åtkomst

Men vi kan möta vissa utmaningar när vi använder den här metoden och vi kommer att komma till det lite senare i denna session.

Demodatatabell och formulär.

Vi behöver en tabell och en blankett. Vi har redan en lämplig tabell med namnet Sample skapat i en tidigare självstudiesession. Om du redan har laddat ner demodatabasen, från den andra länksidan som gavs ovan tidigare, kan du använda den databasen även för denna session. Vi kommer att använda följande objekt från den databasen för våra Drag-Drop-experiment:

  • Tabell:Exempel
  • Form:frmSample

TreeView-kontrollbilden på frmSample med demodata ges nedan som referens:

Du kan ladda ner demodatabasen (ProjectMenu.zip ) från den andra länksidan ovan och extrahera ProjectMenu.accdb databas.

Nytt formulär för Drag Drop-provkörningar.

  1. Öppna databasen ProjectMenu.accdb.

  2. Gör en kopia av tabellen Exempel och namnge det som Sample_bk, förvara det säkert, vi kommer att behöva dess ursprungliga data utan ändringar senare. När vi experimenterar med dra-släpp-metoden är det nödvändigt att uppdatera ParentId-fältvärdet i exempeldemotabellen. Men vi behöver originaldata senare, utan dessa ändringar.

  3. Skapa ett nytt formulär med namnet frmDragDrop .

  4. frmDragDrop Form Design kommer att se ut som bilden nedan när du är klar med den.

  5. Infoga TreeView-kontrollen från ActiveX-kontrollernas lista och placera den i formuläret, lämna tillräckligt med utrymme ovanför kontrollen, så att vi kan skapa två kommandoknappar och en rubriketikett ovanför den. Dra storlekshandtaget i det nedre högra hörnet för att göra det tillräckligt stort för att visa alla noder, utan att rulla.

  6. Ändra namnet Egenskapsvärdet för TreeView Control till TreeView0 .

  7. Infoga en kommandoknapp ovanför och till vänster på TreeView-kontrollen. Ändra dess namn Egenskapsvärde till cmdExpand och Texttext värde till Utöka alla .

  8. Sätt in en andra kommandoknapp ovanför och till höger på TreeView-kontrollen. Ändra dess namn Egenskapsvärde till cmdCollapse och Texttext Egenskapsvärde för att Komprimera alla.
  9. Infoga en etikettkontroll ovanför kommandoknapparna, bred nog för att skriva rubriken som visas ovan, och ändra dess teckensnittsstorlek 14.

  10. Ignorera ImageList-kontrollen, för tillfället har jag kommenterat kodlinjerna som modifierar Node ImageList-indexnumren. Senare kan du importera ImageList-kontrollen med manuellt uppladdade bilder, från vår tidigare självstudiedemodatabas (från den 4:e länksidan ovan) och använda den för att visa nodbilder på noder. När nodpositioner ändras under Drag Drop-åtgärder måste vi ändra nodbilder också beroende på nodens position (rotnivånod eller barnnod) på TreeView-kontrollen.

    Drag-släpp formulärmodulkod.

  11. Visa VBA-kodmodulen för formuläret frmDragDrop, kopiera och klistra in följande VBA-kod (detta är bara den första hälften av formulärmodulkoden) i frmDragDrop-formulärets klassmodul och spara formuläret:

    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

    Jag vet att du är bekant med ovanstående kod, om du redan har gått igenom de tidigare avsnitten, förutom LoadTreeView() subrutin med vissa ändringar. Här har fyllandet av TreeView-noderna delats upp i en tvåstegsprocess.

    Kortfattat, detta är vad som händer i denna subrutin.

    • Alla poster på Exempel Tabeller har laddats som rotnivånoder för TreeView Control, med ett ID-fältvärde som nyckel, i det första steget.

    • Återigen, dessa poster har lästs en andra gång och letar efter ett värde i Föräldra-ID Om det är tomt kommer noden att behållas som rotnivånod.

    • Om fältet ParentID har ett värde identifierar du noden med ParentID-värdet som Node-Key och flytta den nuvarande noden som dess undernod, eller dess [Släkting] Parameter (av Lägg till () Metod) värdet uppdateras.

    • Även om det verkar som att tvåstegs-nodfyllningsproceduren är en onödig övning, finns det en god anledning till att vi måste följa denna metod. Vi kommer att återkomma till detta lite senare och du kommer att veta det utan att behöva förklara mycket.

    • På utformningen av formuläret har jag gett en ImageList-kontroll. Du kan infoga ImageList ActiveX-kontrollen och ladda upp några bilder i den manuellt från disken, eller kopiera och klistra in denna kontroll med bilder från tidigare nedladdningar av demodatabas. I båda fallen, se till att namnet på ImageList-kontrollen är ImageList1 . Annars måste du ändra namnet i koden.

    • Efter det, aktivera de kommenterade raderna i Form_Open() Event Procedure. Aktivera följande rader genom att ta bort kommentarsymbolen från början av raden:

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

    • I TreeView0_ OLEDragDrop() Subrutin (i den andra delen av VBA-koden) aktiverar bildindexparametrarna för noder genom att också ta bort kommentarsymbolerna från dessa rader. Med dessa ändringar kommer nodbilderna att visas på TreeView-kontrollen. Om du har en egen ImageList-kontroll med uppladdade bilder, ändra sedan indexnumren baserat på vilken bild du vill infoga på noderna.

      TreeView0_NodeClick() Händelseprocedur Expanderar den aktuella noden, om barnnoderna är i ett komprimerat tillstånd, annars kommer undernoder att komprimeras. Normalt kontrolleras denna åtgärd (utan kod) genom att klicka på +/- Symbol på trädlinjen för noden med barnnoder.

      Subrutinerna cmdExpand_Click() och cmdCollapse_Click() Händelser Expanderar alla noder och komprimerar alla noder respektive.

      När ovanstående kod körs ser displayen ut som formulärvybilden nedan:

    • Du kan spara frmDragDrop Formulera och öppna den i normalvy. Om allt gick bra kommer du att se ovanstående skärm. Prova Utöka alla och Komprimera alla Kommandoknappar och kontrollera om de också fungerar. Om inte, kontrollera igen att följande inställningar är korrekta eller inte:

    • i) TreeView Controls namn är:TreeView0

    • ii) Visa egenskapsbladet för Exampand All Kommandoknapp och välj [Händelseprocedur] i Vid klick Event Property.

    • iii) Se till att samma inställning är intakt för Komprimera alla Kommandoknappen också.

    • iv) Klicka på en nod med underordnade noder för att se om de komprimeras eller expanderar vid upprepade klick.

    • v) Om ImageList Control placeras på formuläret måste dess namn vara ImageList1 .

      Låt oss fortsätta med den andra delen av VBA-koden som implementerar Drag-Drop-händelserna.

    Andra hälften av VBA-koden.

  12. Kopiera följande andra del av VBA-koden, på frmDragDrop Form Module, som implementerar Drag-Drop-åtgärden, och klistra in den under den befintliga koden:

    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 Dra-Släpp-åtgärden finns det fyra subrutiner, de har körts automatiskt när du drar noden/noden, markerar noden när den flyttas över andra noder och släpper den till sist på en annan nod eller på det tomma området på rotnivå .

Kodens huvudsakliga subrutiner.

  • TreeView0_OLEStartDrag() - Initierar det valda objektet och ställer in noden på Ingenting
  • TreeView0_OLEDragOver() - Fungerar som Mouse Move Event, markerar noden när du drar en nod ovanför den på väg till målnoden.
  • TreeView0_OLEDragDrop() – Utför kontroll och kontroller, placera noden/noderna på den släppta platsen och uppdaterar posten på bastabellen.
  • TreeView0_OLECompleteDrag() - DropHighlight-egenskapen är inställd på Ingenting.

Vi kan dra och släppa med TreeView0_OLEDragDrop() Ensam subrutin. I så fall kommer det inte att finnas någon nodmarkering, när källnoden flyttas över andra noder, från en plats till en annan, förutom att muspekaren ändras till att dra en andra pil bakom den, som i exempelbilden nedan. :

Så vi kommer att uppmärksamma denna subrutin och kontrollera koden i detalj från början. I början av subrutinen har vi deklarerat de nödvändiga noderna och strängvariablerna och andra.

Istället för att upprepa rad-för-rad-analyser här, har jag kommenterat varje rad/avsnitt av koder på ett lämpligt sätt för att du ska förstå vad den gör när du går igenom koden. Du kan gå igenom dem.

Sekvensen av Drap Drop-händelser

Låt oss förstå händelseförloppet som användaren väljer en nod, drar över andra noder på väg till sin slutdestination och Droppar det på målnoden. Eller släpp det på det tomma området på TreeView-kontrollen för att göra det till en rotnivånod.

När du drar en nod över en annan nodtext markeras nodtexten och säger att din nuvarande position är på denna nod på vägen, vart du än ska härifrån. När du flyttar ut från nodtexten försvinner markeringen. Detta händer hela vägen till målnoden. TreeView0_OLEDragOver() Subroutine tar hand om denna framhävningsåtgärd.

När du släpper en nod någonstans visas TreeView0_OLEDragDrop() Subrutin tar överpris. Här måste vi analysera användarens avsikter och vidta lämpliga åtgärder. Följande information måste sparas och analyseras för att flytta noden till rätt plats.

Den viktiga informationen att hålla reda på.

  1. Värden för källnodsreferens, nodnyckel och föräldra-ID, nodunderlag, om några.

  2. Målnoden eller platsreferens, nodnyckel.

  3. Om målet inte är en nod utan det tomma området i TreeView-kontrollen, ska källnoden flyttas till rotnivåpositionen.

  4. Källnoden när den släpps på en annan nod blir målnoden den nya föräldern till källnoden.

  5. Om källnoden har sina egna barn måste de också flyttas med sin förälder.

  6. ** När noden dras och släpps på sin egen överordnade nod, ignorera den här åtgärden.

    ** Kolla till exempel bilden ovan. Om vi ​​drar textrutan Nod och släpp den till dess överordnade nod Kontroller, eller drar kontrollerna Nod och släpp den på dess Form för överordnad nod då kommer dessa drag att ignoreras.

  7. ** Om rotnivå Noden dras och släpps till det tomma området, sedan kommer ingen åtgärd att vidtas eftersom den redan är en nod på rotnivå.

För alla giltiga drag av Node måste vi uppdatera förälder-ID fältvärdet för den relaterade posten på Samplet Tabell.

Nodfall i det tomma området på rotnivå.

När det gäller artikelnummer 3 ovan måste vi skapa en rotnivånod, med samma ID-nummer som källnoden, vilket inte är tillåtet. Duplicerat nyckelvärde är inte tillåtet i TreeView-hierarkin. Detta är det enda området i koden, där du kommer att hitta lite förvirrande om proceduren som följs där.

Proceduren är enligt nedan:

  1. Ändra den befintliga TreeView Node Key genom att lägga till lite extra text, (säg Key X5 ändra till X5Empty ), för att undvika nyckelkonflikter samtidigt som du skapar en tillfällig nod med den ursprungliga nyckeln.

  2. Skapa en tillfällig Nod med originalnyckeln:X5.

  3. Flytta alla undernoder från källnoden, om några, som undernoder till den tillfälliga noden.

  4. Ta bort TreeView-källnoden med den modifierade nyckeln:X5Empty från TreeView-kontrollen, men den relaterade posten i Sample-tabellen berörs inte.

  5. Flytta den tillfälliga Nod med originalnyckeln X5 med sina barn till rotnivåpositionen för TreeView-kontrollen.

  6. Uppdatera ParentID-fältet för den relaterade posten med en nolllängdssträng (“”) för att markera den som en rotnivånod.

Självexperiment med Drag Drop.

Du kan prova några Dra och släpp-experiment själv och se hur det fungerar. Välj en nod, klicka och håll nere vänster musknapp, dra noden och släpp den på en annan nod, eller släpp den i ett tomt område i TreeView-kontrollen. När du drar noden över annan nodtext markeras den och när du är utanför noden slocknar markeringen. Den släpade noden kommer att visas på den nya platsen där du har släppt den. Du kan upprepa detta dra-släpp-experiment genom att välja en enda nod eller nod med barn.

Baserat på denna rörelse av noder den relaterade postens förälder-ID fältvärdet kommer att uppdateras med nyckeln värde (ID) för den målnodsrelaterade posten.

Varför tvåstegs nodfyllningsprocedur?

Nu går vi tillbaka till LoadTreeView() Subrutin, för att ta en andra titt på tvåstegsprocessen som vi har antagit för att fylla alla noder till TreeView-kontrollen.

  • Alla poster i Samplet Tabeller läggs initialt till som noder på rotnivå, med ID-fältvärde som nodnyckel.

  • I det andra passet av posterna, om ParentID-fältvärdet är tomt kommer den noden att förbli som rotnivånod, utan förändring.

  • Alla andra Nod-relaterade poster med ParentID Value flyttas korrekt under dess överordnade Nod.

Naturligtvis kommer frågan upp, varför vi måste göra på det här sättet?

Vi kommer att göra ett enkelt experiment för att göra svaret tydligt utan att förklara det med för många ord. Du kanske redan har gjort några provkörningar med dra och släpp provkörningar själv och omarrangerade noder, och uppdaterade under processen dessa posts ParentID-värden med ändringen. Så vi måste återställa postvärdena till deras ursprungliga tillstånd i Samplet Tabell, innan vi startar en ny demo.

Vi har redan skapat en kopia av vårt Exempel tidigare, med namnet Sample_bk som backup. Ta bort provet Tabell och gör en kopia från Sample_bk med det ursprungliga namnet:Exempel .

Öppna tabellen och visa posterna och deras föräldra-ID-fältvärden. Exempelbilden av tabellen ges nedan:

ID-fältvärdena är AutoNumbers och de är alla i sekventiell ordning och alla ID-värden är unika. Följande enkla regel styr tillägget av en underordnad nod till TreeView-kontrollen.

Den enkla barnnodregeln: Föräldra-ID fältvärde (föräldernyckel ) i en post förväntar sig att en överordnad nod redan finns i TreeView-kontrollen, med samma värde som Node-Key (ID:t).

Kontrollera den tredje posten från toppen, i tabellbilden ovan. Fältvärdet för ParentID är 2 och ID för den aktuella posten är 3. I det här fallet kommer posten med ID 2 att läggas till i TreeView Control innan vi försöker lägga till den tredje posten till Noden. Båda skivorna är inte nödvändigtvis bredvid varandra. Kontrollera posten med ID-nummer 21, dess ParentID-fältvärde är 12, mindre än det aktuella postens ID-värde 21.

I båda fallen, när programmet stöter på ParentID-värdet i en post, antar det att posten med ID-värdet lika med ParentID redan lagts till som en Nod i TreeView-kontrollen i den tidigare cykeln för att fylla noderna.

Motivering av tvåstegsproceduren.

Låt oss prova några Drag-Drop testkörningar. Men innan dess har vi ett formulär med namnet frmSample, som vi har använt i den första handledningssessionen, och i det har vi laddat alla TreeView-noder på en gång. Ja, vi har följt samma metod hittills och vi behöver lite förändring från och med nu. Men innan dess, låt oss öppna det gamla formuläret och se hur noderna visas på formuläret.

  1. Öppna formuläret frmSample för att se hur TreeView-visningen ser ut, med exempeltabellposterna, laddade med den gamla regeln.

  2. Om du har tittat igenom TreeView-noderna så stäng formuläret.

  3. Öppna nu frmDragDrop Form. Vi förbereder att dra och släppa en nod.

  4. Välj noden med nod-text tabell, Klicka och håll nere vänster musknapp, dra och släpp den på noden med Formulären för nodtext.

  5. Tabell Nod med dess omedelbara Child-Node fält och dess undernoder flyttas som undernoder under formuläret Nod.

  6. Stäng formuläret frmDragDrop och öppna den igen. Noderna kommer att visas korrekt, där du har släppt dem, som bilden nedan.

  7. Stäng nu formuläret frmDragDrop.

  8. Öppna formuläret frmSample för att se hur denna ändring visas på detta formulär. Du kommer att hälsas med ett felmeddelande, Element hittades inte med Felnummer:35601.

  9. Välj kommandoknappen Debug för att gå till den markerade kodraden, där fel uppstod.

  10. Peka med musen på nodKey Param för Add()-metoden visar X3, punkt musen på ParentKey parametern och den visar X7.

    När vi tittar på dessa två parametervärden kan vi anta att vi är på posten med ID-värdet 3 och försöker ange denna Nod som en underordnad Nod, till en annan Nod som ännu inte har fyllts i TreeView-kontrollen, med ID-värde 7.

  11. Tryck på F5 Nyckel för att visa samma dialogruta igen och klicka på Avsluta Kommandoknapp för att stoppa programmet och visa formuläret i databasfönstret. Stäng frmSample Form.

  12. Öppna Exempel Tabell för att se arrangemanget av ParentID-numren, efter vår dra och släpp-åtgärd. Posterna kommer att se ut som bilden nedan och jag har markerat posten som utlöste felet med ParentID-värdet 7 och visar dess överordnade postposition.

Efter den tidigare noden som fyller i normal procedur är vi på tredje postpositionen. Eftersom posterna ParentID-värde 7, Nod med ID-värde 7 måste finnas i TreeView-kontrollen. Noden med ID-värde 7 är ännu inte ifylld i TreeView-kontrollen, men vi försöker referera till den icke-existerande noden och detta utlöser ett fel.

Även om du sorterar posterna i ParentID-fältordningen kommer posternas nya arrangemang att se ut som bilden nedan:

Nu är en annan posts föräldranod inte i den förväntade positionen.

Under dessa omständigheter fungerar därför vår tvåstegsladdning av TreeView Nodes för både normala och efter dra-släpp-åtgärder.

I det första steget fyller du i alla poster som noder på rotnivå i TreeView-kontrollen med ID-fältvärdet som nodnyckel.

Nu är alla noder för alla poster tillgängliga i TreeView-kontrollen. Det blir lätt att flytta runt dem vart vi vill. Det står inte att någon av de nödvändiga noderna inte finns i 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 och VBA
  2. MS-Access VBA Class Object Arrays
  3. MS-Access basklass och härledda objekt
  4. VBA Base Class and Derived Object-2
  5. Basklass- och härledda objektvarianter
  6. MS-Access Recordset och Class Module
  7. Åtkomst till klassmoduler och omslagsklasser
  8. Omvandling av omslagsklassfunktionalitet


  1. Uppgradering till PostgreSQL 11 med logisk replikering

  2. NEW_TIME() Funktion i Oracle

  3. MariaDB JSON_VALID() Förklarad

  4. Hur man tömmer en MySQL-databas