Introduktion.
Jeg håber, du fandt sidste uges selvstudie om ImageCombo Control nyttig til dine Microsoft Access-projekter. Med TreeView ImageCombo Control kunne vi skabe en smuk rullemenu med flere muligheder og rumme den i et lille rum på formularen.
Ligeledes har vi i en tidligere session lært, hvordan man tilføjer nye noder på et bestemt sted i nodehierarkiet eller sletter en node og tilføjer en ny for at flytte en node på trævisningskontrollen.
Denne metode anmoder om oprettelse af en ny post i kildetabellen for den nye node. Eller slet en eksisterende post og opret en ny for at flytte en eksisterende node for at gøre den permanent. På en måde, med brugen af Tilføj/Slet funktioner, kunne vi tilføje nye noder eller omarrangere de eksisterende noder på TreeView-kontrollen. Hvad angår omarrangering af noder, har vi en bedre måde at gøre det på, i stedet for at slette noder og genskabe dem. Træk noden fra dens aktuelle placering, og slip den, hvor vi ønsker, at den skal være på TreeView-kontrollen. Dette er, hvad vi skal lære i denne episode
Denne enkle tilgang behøver kun at opdatere ændringen af ParentID-feltværdien for relaterede poster for at gøre ændringen permanent.
De emner, der hidtil er dækket i tidligere sessioner.
- Microsoft TreeView Control Tutorial
- Oprettelse af adgangsmenu med TreeView-kontrol
- Tildeling af billeder til TreeView-kontrol
- Tildeling af billeder til TreeView Control-2
- TreeView Control Check-Mark Tilføj slet noder
- TreeView ImageCombo Drop-down Adgangsmenu
Men vi kan stå over for nogle udfordringer, mens vi bruger denne metode, og det kommer vi til lidt senere i denne session.
Demodatatabel og formular.
Vi har brug for en tabel og en formular. Vi har allerede en passende tabel med navnet Sample oprettet i en tidligere selvstudiesession. Hvis du allerede har downloadet demodatabasen fra den anden linkside, der er givet ovenfor, kan du også bruge denne database til denne session. Vi vil bruge følgende objekter fra den database til vores Drag-Drop-eksperimenter:
- Tabel:Eksempel
- Formular:frmSample
TreeView-kontrolbilledet på frmSample med demodata er givet nedenfor til reference:
Du kan downloade demodatabasen (ProjectMenu.zip ) fra den anden linkside ovenfor, og udtræk ProjectMenu.accdb database.
Ny formular til træk-slip-prøvekørsler.
-
Åbn ProjectMenu.accdb-databasen.
-
Lav en kopi af tabellen Eksempel og navngiv den som Sample_bk, hold det sikkert, vi skal bruge dets originale data uden ændringer senere. Når vi eksperimenterer med træk-slip-metoden, er det nødvendigt at opdatere ParentId-feltets værdi på prøvedemotabellen. Men vi har brug for de originale data senere, uden disse ændringer.
-
Opret en ny formular med navnet frmDragDrop .
-
frmDragDrop Form Design vil se ud som billedet nedenfor, når du er færdig med det.
-
Indsæt TreeView-kontrolelementet fra ActiveX-kontrolelementernes liste, og placer det på formularen, og efterlad nok plads over kontrolelementet, så vi kan oprette to kommandoknapper og en overskriftsmærke over den. Træk størrelseshåndtaget i nederste højre hjørne for at gøre det stort nok til at vise alle noderne uden at rulle.
-
Skift navnet Egenskabsværdi for TreeView Control til TreeView0 .
-
Indsæt en kommandoknap over og venstre kant af TreeView-kontrolelementet. Skift dens navn Ejendomsværdi til cmdExpand og Billedtekst værdi til Udvid alle .
- Indsæt en anden kommandoknap over og til højre kant af TreeView-kontrolelementet. Skift dens navn Egenskabsværdi til cmdCollapse og Billetten Ejendomsværdi til Skjul alle.
-
Indsæt en etiketkontrol over kommandoknapperne, bred nok til at skrive overskriften som vist ovenfor, og skift dens skriftstørrelse 14.
-
Ignorer ImageList Control, for øjeblikket har jeg kommenteret kodelinjerne, der ændrer Node ImageList-indeksnumrene. Senere kan du importere billedlistekontrollen med manuelt uploadede billeder fra vores tidligere selvstudiedemodatabase (fra den 4. linkside ovenfor) og bruge den til at vise nodebilleder på noder. Når nodepositioner ændres under træk-slip-handlinger, skal vi også ændre nodebilleder afhængigt af nodens position (rodniveauknude eller børneknude) på TreeView-kontrollen.
Træk-slip formularmodulkode.
-
Vis VBA-kodemodulet for formularen frmDragDrop, kopier og indsæt følgende VBA-kode (dette er kun den første halvdel af formularmodulkoden) i frmDragDrop-formularens klassemodul og gem formularen:
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
Jeg ved, at du er bekendt med ovenstående kode, hvis du allerede har gennemgået de tidligere episoder, undtagen LoadTreeView() subrutine med nogle ændringer. Her er udfyldning af TreeView-noder blevet opdelt i en to-trins proces.
Kort fortalt er dette, hvad der sker i denne underrutine.
Alle posterne på Eksempel Tabellen er blevet indlæst som knudepunkter på rodniveau i TreeView Control, med en ID-feltværdi som Nøgle, i det første trin.
Igen er disse poster blevet læst en anden gang, og kontroller for en værdi i Forældre-id felt, hvis det er tomt, vil noden blive bibeholdt som node på rodniveau.
Hvis ParentID-feltet har en Value, skal du identificere noden med ParentID-værdien som Node-Key og flyt den aktuelle node som dens underordnede node eller dens [Selativ] Parameter (af Tilføj () Metode) værdi bliver opdateret.
-
Selvom det ser ud til, at to-trins node-udfyldningsproceduren er en unødvendig øvelse, er der en god grund til, at vi er nødt til at følge denne metode. Vi vil vende tilbage til dette lidt senere, og du vil vide det uden meget forklaring.
-
På Formularens Design har jeg givet en ImageList Control. Du kan indsætte ImageList ActiveX Control og upload nogle billeder i det manuelt fra disken, eller kopier og indsæt denne kontrol med billeder fra tidligere download af demodatabaser. I begge tilfælde skal du sørge for, at navnet på ImageList-kontrollen er ImageList1 . Ellers skal du ændre navnet i koden.
-
Aktiver derefter de kommenterede linjer i Form_Open() Event Procedure. Aktiver følgende linjer ved at fjerne kommentarsymbolet fra begyndelsen af linjen:
'Set imgListObj = Me.ImageList1.Object 'tv.ImageList = imgListObj
-
I TreeView0_ OLEDragDrop() Subrutine (i 2. del af VBA-koden) aktiverer billedindeksparametrene for noder ved også at fjerne kommentarsymbolerne fra disse linjer. Med disse ændringer vil nodebillederne blive vist på TreeView Control. Hvis du har din egen billedlistekontrol med uploadede billeder, skal du ændre indeksnumrene baseret på det billede, du gerne vil indsætte på noderne.
TreeView0_NodeClick() Hændelsesprocedure Udvider den aktuelle node, hvis underordnede knudepunkter er i en sammenklappet tilstand, ellers vil underknudepunkter blive skjult. Normalt styres denne handling (uden kode) ved at klikke på +/- Symbol på trælinjen for noden med underordnede noder.
Underrutinerne cmdExpand_Click() og cmdCollapse_Click() Hændelser Udvider henholdsvis alle noder og skjuler alle noder.
Når ovenstående kode kører, ser displayet ud som formularvisningsbilledet vist nedenfor:
-
Du kan gemme frmDragDrop Form og åbn den i normal visning. Hvis alt gik godt, vil du se ovenstående skærm. Prøv Udvid alle og Skjul alle Kommandoknapper og kontroller, om de også virker. Hvis ikke, så kontroller igen, at følgende indstillinger er korrekte eller ej:
-
i) TreeView Controls navn er:TreeView0
-
ii) Vis egenskabsarket for Exampand All Kommandoknap, og vælg [Begivenhedsprocedure] i Ved klik Begivenhedsejendom.
-
iii) Sørg for, at den samme indstilling er intakt for Skjul alle Kommandoknap også.
-
iv) Klik på en node, der har underordnede noder, for at se, om de kollapser eller udvides ved gentagne klik.
-
v) Hvis ImageList Control er placeret på formularen, skal dens navn være ImageList1 .
Lad os fortsætte med den anden del af VBA-koden, der implementerer Drag-Drop-begivenhederne.
Anden halvdel af VBA-koden.
-
Kopier følgende anden del af VBA-koden på frmDragDrop Form Module, der implementerer Drag-Drop handlingen, og indsæt den under den eksisterende kode:
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
Til Drag-Drop-handlingen er der fire underrutiner, de udføres automatisk, når du trækker noderne, fremhæver noden, når den flyttes over andre noder, og til sidst slipper den på en anden node eller på det tomme område på rodniveau .
Kodens vigtigste underrutiner.
- TreeView0_OLEStartDrag() - Initialiserer det valgte element og indstiller noden til ingenting
- TreeView0_OLEDragOver() - Fungerer som Mouse Move Event, fremhæver noden, når der trækkes en node over den, på vej til målknuden.
- TreeView0_OLEDragDrop() – Udfører kontrol og kontroller, placerer noderne i den droppede placering og opdaterer posten på basistabellen.
- TreeView0_OLEcompleteDrag() - DropHighlight-egenskaben er indstillet til Ingenting.
Vi kan udføre træk og slip med TreeView0_OLEDragDrop() Subrutine alene. I så fald vil der ikke være nogen node-fremhævning, når kildenoden bevæger sig over andre noder, fra det ene sted til det andet, bortset fra at musemarkøren skifter til at trække en anden pil bag sig, som i eksempelbilledet nedenfor :
Så vi vil være opmærksomme på denne subrutine og kontrollere koden i detaljer fra begyndelsen. I begyndelsen af subrutinen har vi erklæret de nødvendige noder og strengvariabler og andre.
I stedet for at gentage linje-for-linje analyser her, har jeg kommenteret hver linje/afsnit af koder passende, så du forstår, hvad den gør, når du gennemgår koden. Du kan gå dem igennem.
Rækkefølgen af Drap Drop-begivenheder
Lad os forstå rækkefølgen af begivenheder, brugeren vælger en node, trækker hen over andre noder på vej til dens endelige destination og Drops det på Target Node. Eller slip det på det tomme område på TreeView Control for at gøre det til en knude på rodniveau.
Når du trækker en node hen over en anden node-tekst, bliver node-teksten fremhævet og siger, at din nuværende position er på denne node på vej, uanset hvor du skal hen herfra. Når den flyttes ud af node-teksten, forsvinder fremhævelsen. Dette sker hele vejen igennem til Target Node. TreeView0_OLEDragOver() Subroutine tager sig af denne fremhævende handling.
Når du taber en node et sted, vises TreeView0_OLEDragDrop() Subrutine tager overpris. Her skal vi analysere brugerens hensigter og træffe passende foranstaltninger. Følgende information skal gemmes og analyseres for at flytte noden til den korrekte placering.
Vigtige oplysninger at holde styr på.
-
Kilden nodereference, nodenøgle og forældre-id værdier, node børn, hvis nogen.
-
Målknude eller placeringsreference, nodenøgle.
-
Hvis målet ikke er en knude, men det tomme område i TreeView-kontrollen, skal kildenoden flyttes til positionen på rodniveau.
-
Kildeknuden, når den droppes på en anden knude, bliver målknuden den nye overordnede for kildenoden.
-
Hvis Source Node har sine egne børn, skal de også flyttes med deres forældre.
-
** Når noden trækkes og slippes på sin egen forældrenode, skal du ignorere denne handling.
** Tjek for eksempel billedet ovenfor. Hvis vi trækker tekstboksen Node og slip den til dens overordnede node Kontroller, eller trækker kontrollerne Node og slip den på dens overordnede node Form så vil disse træk blive ignoreret.
-
** Hvis rodniveau Node trækkes og slippes ind i det tomme område, hvorefter der ikke foretages nogen handling, fordi det allerede er en node på rodniveau.
For alle gyldige træk af Node skal vi opdatere Forældre-ID'et feltværdi for den relaterede post på Sample tabel.
Knudefald i det tomme område på rodniveau.
I tilfælde af varenummer 3 ovenfor, skal vi oprette en knude på rodniveau med det samme ID-nummer som kildenoden, hvilket ikke er tilladt. Dubleret nøgleværdi er ikke tilladt i TreeView-hierarkiet. Dette er det eneste område af kodekset, hvor du vil finde lidt forvirring om den procedure, der følges der.
Fremgangsmåden er som angivet nedenfor:
-
Rediger den eksisterende TreeView Node Key med tilføjelse af noget ekstra tekst, (sig Key X5 ændre til X5Empty ), for at undgå nøglekonflikter, mens du opretter en midlertidig node med den originale nøgle.
-
Opret en midlertidig Node med den originale nøgle:X5.
-
Flyt alle underordnede noder fra kildenoden, hvis nogen, som underordnede noder til den midlertidige node.
-
Slet TreeView-kildenoden med den ændrede nøgle:X5Empty fra TreeView Control, men den relaterede post på prøvetabellen berøres ikke.
-
Flyt den midlertidige Node med den originale nøgle X5 med sine børn til rodniveaupositionen i TreeView Control.
-
Opdater ParentID-feltet for den relaterede post med en nul-længde streng (“”) for at markere den som en node på rodniveau.
Selveksperimenter med Drag Drop.
Du kan selv prøve nogle træk og slip-eksperimenter og se, hvordan det fungerer. Vælg en node, klik og hold venstre museknap nede, træk noden, og slip den på en anden node, eller slip den i et tomt område af TreeView Control. Når du trækker noden hen over anden node-tekst, fremhæves den, og når du er ude af noden, forsvinder markeringen. Den trukne node vises på den nye placering, hvor du har droppet den. Du kan gentage dette træk-slip-eksperiment ved at vælge en enkelt node eller node med børn.
Baseret på denne bevægelse af noder den relaterede posts Forældre-ID feltværdien vil blive opdateret med Nøglen værdi (ID) af den målknuderelaterede post.
Hvorfor to-trins nodeudfyldningsprocedure?
Nu går vi tilbage til LoadTreeView() Underrutine, for at tage et andet kig på den to-trins proces, vi har vedtaget til at udfylde alle noder til TreeView Control.
-
Alle poster i Eksempel Tabeller tilføjes til at begynde med som knudepunkter på rodniveau, ved at bruge ID-feltværdien som nodenøgle.
-
I det andet gennemløb af posterne, hvis ParentID-feltværdien er tom, forbliver den node som rodniveauknude uden ændring.
-
Alle andre noder-relaterede poster med forældre-id-værdi flyttes korrekt under dens overordnede node.
Spørgsmålet dukker naturligvis op, hvorfor vi skal gøre det på denne måde?
Vi vil lave et simpelt eksperiment for at gøre svaret klart uden at forklare det med for mange ord. Du har måske allerede lavet nogle prøvekørsler med træk og slip prøvekørsler selv og omarrangerede noder, og i processen opdaterede du disse posters ParentID-værdier med ændringen. Så vi er nødt til at nulstille postværdierne til deres oprindelige tilstand i Samplen Tabel, før vi starter en ny demo.
Vi har allerede oprettet en kopi af vores Tabel Eksempel tidligere med navnet Sample_bk som backup. Slet eksemplet Tabel og lav en kopi fra Sample_bk med det originale navn:Eksempel .
Åbn tabellen, og se posterne og deres forældre-id-feltværdier. Eksempelbilledet af tabellen er givet nedenfor:
ID-feltværdierne er autonumre, og de er alle i sekventiel rækkefølge, og alle id-værdier er unikke. Den følgende enkle regel styrer tilføjelsen af en underordnet node til TreeView-kontrollen.
Den simple børneknuderegel: Forældre-id feltværdi (forældrenøgle ) i en post forventer, at der allerede eksisterer en overordnet node i TreeView Control, med samme værdi som Node-Key (ID'et).
Tjek den tredje post fra toppen i ovenstående tabelbillede. Værdien af ParentID-feltet er 2, og ID'et for den aktuelle post er 3. I dette tilfælde vil posten med ID 2 blive tilføjet til TreeView Control, før vi forsøger at tilføje den tredje post til Noden. Begge plader er ikke nødvendigvis ved siden af hinanden. Tjek posten med ID-nummer 21, dens ParentID-feltværdi er 12, mindre end den aktuelle records ID-værdi 21.
I begge tilfælde, når programmet støder på ParentID-værdien i en post, antager det, at posten med ID-værdien lig med ParentID'et allerede var tilføjet som en node i TreeView-kontrollen i den tidligere cyklus med udfyldning af noderne.
Begrundelse af totrinsproceduren.
Lad os prøve nogle Drag-Drop prøvekørsler. Men før det har vi en formular med navnet frmSample, som vi har brugt i den første vejledningssession, og i den forbindelse har vi indlæst alle TreeView-noder på én gang. Ja, vi har fulgt den samme metode indtil videre, og vi har brug for nogle ændringer fra nu af. Men før det, lad os åbne den gamle formular og se, hvordan noderne vises på formularen.
-
Åbn formularen frmSample for at se, hvordan TreeView-displayet ser ud med prøvetabelposterne indlæst ved hjælp af den gamle regel.
-
Hvis du er færdig med at se TreeView-knuderne, så luk formularen.
-
Åbn nu frmDragDrop Form. Vi forbereder at trække og slippe en node.
-
Vælg noden med node-tekst tabellen, Klik og hold venstre museknap nede, træk og slip den på noden med node-tekst-formularen.
-
Tabellen Node med dens umiddelbare Child-Node felter og dets børneknuder flyttes som underordnede noder under formularen Node.
-
Luk formularen frmDragDrop og åbne den igen. Noderne vises korrekt, hvor du har droppet dem, ligesom billedet nedenfor.
-
Luk nu formularen frmDragDrop.
-
Åbn formularen frmSample for at se, hvordan denne ændring vises på denne formular. Du vil blive mødt med en fejlmeddelelse, Element ikke fundet med Fejlnummer:35601.
-
Vælg kommandoknappen Debug for at gå til den fremhævede kodelinje, hvor fejlen opstod.
-
Peg med musen på nodKey Param af Add()-metoden viser X3, punkt musen på Parent Key parameter, og den viser X7.
Når vi ser på disse to parameterværdier, kan vi antage, at vi er på posten med ID-værdien 3 og forsøger at udpege denne Node som en underordnet Node, til en anden Node, der endnu ikke er udfyldt i TreeView Control, med ID-værdi 7.
-
Tryk på F5 Tast for at åbne den samme dialogboks igen, og klik på Afslut Kommandoknap for at stoppe programmet og få formularen frem i databasevinduet. Luk frmSample Form.
-
Åbn Eksempel Tabel for at se arrangementet af forældre-id-numrene efter vores træk og slip-handling. Posterne vil se ud som billedet nedenfor, og jeg har fremhævet den post, der udløste fejlen med ParentID-værdien 7 og viser dens overordnede rekordposition.
Efter den tidligere node, der udfyldte normal procedure, er vi på den tredje rekordposition. Siden registrerer forældre-ID-værdi 7, Nikke med ID-værdi 7 skal være til stede i TreeView Control. Noden med ID-værdi 7 er endnu ikke udfyldt i TreeView Control, men vi forsøger at referere til den ikke-eksisterende node, og dette udløser en fejl.
Selvom du sorterer posterne i ParentID-feltrækkefølgen, vil posternes nye arrangement se ud som billedet nedenfor:
Nu er en anden rekords forældreknude ikke i den forventede position.
Derfor, under disse omstændigheder, fungerer vores to-trins TreeView Nodes-indlæsningstilgang til både normale og efter træk-slip-handlinger.
I det første trin skal du udfylde alle poster som noder på rodniveau i TreeView-kontrolelementet ved at bruge ID-feltværdien som Node-Key.
Nu er alle noder i alle poster tilgængelige i TreeView Control. Det vil være nemt at flytte dem rundt, hvorhen vi vil. Det siger ikke, at nogen af de nødvendige noder ikke eksisterer i TreeView.
I den anden gennemgang af det samme sæt poster er posterne med tomme ParentID-feltværdier uberørte og får lov til at forblive som knudepunkter på rodniveau. I andre tilfælde flytter noden som underordnet node under dens overordnede node ved at opdatere [Relativ] Parameter for noden med følgende sætning:
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
- MS-Access Class Module og VBA
- MS-Access VBA Class Object Arrays
- MS-Access Basisklasse og afledte objekter
- VBA Base Class and Derived Object-2
- Basisklasse og afledte objektvarianter
- MS-Access Recordset og Class Module
- Adgang til klassemodul- og indpakningsklasser
- Wrapper Class Funktionalitet Transformation