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.
- Microsoft TreeView Control Tutorial
- Skapa åtkomstmeny med TreeView-kontroll
- Tilldela bilder till TreeView-kontroll
- Tilldela bilder till TreeView Control-2
- TreeView Control Markera Lägg till Ta bort noder
- 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.
-
Öppna databasen ProjectMenu.accdb.
-
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.
-
Skapa ett nytt formulär med namnet frmDragDrop .
-
frmDragDrop Form Design kommer att se ut som bilden nedan när du är klar med den.
-
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.
-
Ändra namnet Egenskapsvärdet för TreeView Control till TreeView0 .
-
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 .
- 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.
-
Infoga en etikettkontroll ovanför kommandoknapparna, bred nog för att skriva rubriken som visas ovan, och ändra dess teckensnittsstorlek 14.
-
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.
-
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.
-
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å.
-
Värden för källnodsreferens, nodnyckel och föräldra-ID, nodunderlag, om några.
-
Målnoden eller platsreferens, nodnyckel.
-
Om målet inte är en nod utan det tomma området i TreeView-kontrollen, ska källnoden flyttas till rotnivåpositionen.
-
Källnoden när den släpps på en annan nod blir målnoden den nya föräldern till källnoden.
-
Om källnoden har sina egna barn måste de också flyttas med sin förälder.
-
** 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.
-
** 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:
-
Ä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.
-
Skapa en tillfällig Nod med originalnyckeln:X5.
-
Flytta alla undernoder från källnoden, om några, som undernoder till den tillfälliga noden.
-
Ta bort TreeView-källnoden med den modifierade nyckeln:X5Empty från TreeView-kontrollen, men den relaterade posten i Sample-tabellen berörs inte.
-
Flytta den tillfälliga Nod med originalnyckeln X5 med sina barn till rotnivåpositionen för TreeView-kontrollen.
-
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.
-
Öppna formuläret frmSample för att se hur TreeView-visningen ser ut, med exempeltabellposterna, laddade med den gamla regeln.
-
Om du har tittat igenom TreeView-noderna så stäng formuläret.
-
Öppna nu frmDragDrop Form. Vi förbereder att dra och släppa en nod.
-
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.
-
Tabell Nod med dess omedelbara Child-Node fält och dess undernoder flyttas som undernoder under formuläret Nod.
-
Stäng formuläret frmDragDrop och öppna den igen. Noderna kommer att visas korrekt, där du har släppt dem, som bilden nedan.
-
Stäng nu formuläret frmDragDrop.
-
Ö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.
-
Välj kommandoknappen Debug för att gå till den markerade kodraden, där fel uppstod.
-
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.
-
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.
-
Ö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
- MS-Access Class Module och VBA
- MS-Access VBA Class Object Arrays
- MS-Access basklass och härledda objekt
- VBA Base Class and Derived Object-2
- Basklass- och härledda objektvarianter
- MS-Access Recordset och Class Module
- Åtkomst till klassmoduler och omslagsklasser
- Omvandling av omslagsklassfunktionalitet