sql >> Databáze >  >> RDS >> Access

Uspořádejte uzly TreeView přetažením

Úvod.

Doufám, že jste našli výukový program z minulého týdne o ImageCombo Control užitečný pro vaše projekty Microsoft Access. S ovládacím prvkem TreeView ImageCombo Control bychom mohli vytvořit krásnou rozbalovací nabídku s několika možnostmi a umístit ji do malého prostoru ve formuláři.

Podobně jsme se v dřívější relaci naučili, jak přidat nové uzly do konkrétního umístění v hierarchii uzlů nebo odstranit uzel a přidat nový uzel pro přemístění uzlu v ovládacím prvku stromového zobrazení.

Tato metoda vyžaduje vytvoření nového záznamu ve zdrojové tabulce pro nový uzel. Nebo odstraňte existující záznam a vytvořte nový, abyste přesunuli existující uzel, aby byly trvalé. Svým způsobem pomocí funkcí Přidat/Odstranit bychom mohli přidat nové uzly nebo přeuspořádat stávající uzly v ovládacím prvku TreeView. Pokud jde o přeuspořádání uzlů, máme lepší způsob, jak to udělat, než mazat uzly a znovu je vytvářet. Přetáhněte uzel z jeho aktuálního umístění a pusťte jej tam, kde chceme, aby byl v ovládacím prvku TreeView. To je to, co se naučíme v této epizodě

Tento jednoduchý přístup vyžaduje pouze aktualizaci změny hodnoty pole ParentID souvisejících záznamů, aby byla změna trvalá.

Dosud probíraná témata v dřívějších relacích.

  1. Výukový program pro ovládání Microsoft TreeView
  2. Vytvoření přístupové nabídky pomocí TreeView Control
  3. Přiřazení obrázků k ovládacímu prvku TreeView
  4. Přiřazení obrázků k TreeView Control-2
  5. Ovládací prvek TreeView zaškrtněte políčko Přidat a odstranit uzly
  6. Rozbalovací nabídka přístupu TreeView ImageCombo

Při používání této metody však můžeme čelit určitým problémům a na to přijdeme o něco později v této sekci.

Tabulka ukázkových dat a formulář.

Potřebujeme tabulku a formulář. Již máme vhodnou tabulku s názvem Ukázka vytvořené v dřívější relaci výukového programu. Pokud jste si již stáhli ukázkovou databázi z druhé stránky odkazu uvedené výše, můžete tuto databázi použít také pro tuto relaci. Pro naše experimenty Drag-Drop použijeme následující objekty z této databáze:

  • Tabulka:Ukázka
  • Formulář:frmSample

Ovládací obrázek TreeView na frmSample s ukázkovými daty je uveden níže:

Můžete si stáhnout ukázkovou databázi (ProjectMenu.zip ) z druhé stránky odkazu uvedené výše a extrahujte ProjectMenu.accdb databáze.

Nový formulář pro zkušební běhy Drag Drop.

  1. Otevřete databázi ProjectMenu.accdb.

  2. Vytvořte kopii tabulky Ukázka a pojmenujte jej jako Sample_bk, uchovejte jej v bezpečí, jeho původní data budeme později beze změny potřebovat. Když experimentujeme s metodou drag-drop, je nutné aktualizovat hodnotu pole ParentId na ukázkové ukázkové tabulce. Původní data však potřebujeme později, bez těchto změn.

  3. Vytvořte nový formulář s názvem frmDragDrop .

  4. FrmDragDrop Form Design bude po dokončení vypadat jako na obrázku níže.

  5. Vložte ovládací prvek TreeView ze seznamu ovládacích prvků ActiveX a umístěte jej na formulář, přičemž nad ovládacím prvkem ponechejte dostatek místa, abychom nad ním mohli vytvořit dvě příkazová tlačítka a nadpis. Přetáhněte úchyt pro změnu velikosti v pravém dolním rohu tak, aby byl dostatečně velký na zobrazení všech uzlů bez posouvání.

  6. Změňte Jméno Hodnota vlastnosti ovládacího prvku TreeView na TreeView0 .

  7. Vložte příkazové tlačítko nad a levý okraj ovládacího prvku TreeView. Změňte jeho Název Hodnota vlastnosti na cmdExpand a Titulek hodnotu Rozbalit vše .

  8. Vložte druhé příkazové tlačítko nad a na pravý okraj ovládacího prvku TreeView. Změňte jeho Název Hodnota vlastnosti na cmdCollapse a Titulek Hodnota vlastnosti Sbalit vše
  9. Vložte ovládací prvek štítku nad příkazová tlačítka dostatečně široký, aby bylo možné napsat nadpis, jak je znázorněno výše, a změňte jeho velikost písma 14.

  10. Ignorujte ovládací prvek ImageList, prozatím jsem okomentoval řádky kódu, které upravují čísla indexu seznamu obrázků Node. Později můžete importovat ovládací prvek ImageList s ručně nahranými obrázky z naší dřívější ukázkové databáze výukového programu (z výše uvedené 4. stránky odkazů) a použít jej k zobrazení obrázků uzlů na uzlech. Když se pozice uzlů změní během akcí Drag Drop, musíme změnit obrázky uzlů také v závislosti na pozici uzlu (uzel na kořenové úrovni nebo podřízený uzel) v ovládacím prvku TreeView.

    Kód modulu formuláře přetažením.

  11. Zobrazte modul kódu VBA formuláře frmDragDrop, zkopírujte a vložte následující kód VBA (toto je pouze první polovina kódu modulu formuláře) do modulu třídy formuláře frmDragDrop a uložte formulář:

    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

    Vím, že výše uvedený kód znáte, pokud jste již prošli předchozími epizodami, kromě LoadTreeView() podprogram s některými změnami. Zde bylo naplnění uzlů TreeView rozděleno do dvou kroků.

    Stručně řečeno, toto se děje v tomto podprogramu.

    • Všechny záznamy na Ukázka Tabulka byla v prvním kroku načtena jako kořenové uzly TreeView Control s hodnotou pole ID jako klíčem.

    • Tyto záznamy byly znovu přečteny podruhé a zkontrolována hodnota v ParentId Pokud je pole prázdné, uzel bude zachován jako uzel na kořenové úrovni.

    • Pokud má pole ParentID hodnotu, identifikujte uzel s hodnotou ParentID jako Klíč uzlu a přesunout aktuální uzel jako jeho podřízený uzel nebo jeho [Relativní] Parametr (z Přidat () Metoda) hodnota se aktualizuje.

    • I když se zdá, že dvoukrokový postup naplnění uzlů je zbytečným cvičením, existuje dobrý důvod, proč musíme postupovat podle této metody. K tomu se vrátíme později a budete to vědět bez velkého vysvětlování.

    • U návrhu formuláře jsem dal ovládací prvek ImageList. Můžete vložit Ovládací prvek ImageList ActiveX a nahrajte do něj nějaké obrázky ručně z disku, nebo zkopírujte a vložte tento ovládací prvek s obrázky z dřívějších stažení demo databáze. V obou případech se prosím ujistěte, že název ovládacího prvku ImageList je ImageList1 . V opačném případě musíte změnit název v kódu.

    • Poté povolte řádky s komentářem v Event Procedure Form_Open(). Povolte následující řádky odstraněním symbolu komentáře ze začátku řádku:

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

    • V TreeView0 OLEDragDrop() Podprogram (ve 2. části kódu VBA) umožňuje parametry indexu obrázku uzlů odstraněním symbolů komentářů z těchto řádků. S těmito změnami se obrazy uzlů objeví v ovládacím prvku TreeView. Pokud máte vlastní ovládací prvek ImageList s nahranými obrázky, změňte indexová čísla podle toho, jaký obrázek chcete vložit do uzlů.

      Funkce TreeView0_NodeClick() Event Procedure Rozbalí aktuální uzel, pokud jsou podřízené uzly ve sbaleném stavu, jinak budou podřízené uzly sbalené. Normálně se tato akce ovládá (bez kódu) kliknutím na +/- Symbol na stromové linii uzlu s podřízenými uzly.

      Podprogramy cmdExpand_Click() a cmdCollapse_Click() Události Rozbalí všechny uzly a sbalí všechny uzly.

      Když se výše uvedený kód spustí, zobrazení vypadá jako níže uvedený obrázek zobrazení formuláře:

    • Můžete uložit frmDragDrop Formulář a otevřete jej v normálním zobrazení. Pokud vše proběhlo v pořádku, uvidíte výše uvedenou obrazovku. Vyzkoušejte Rozbalit vše a Sbalit vše Příkazová tlačítka a zkontrolujte, zda také fungují. Pokud ne, znovu zkontrolujte, zda jsou následující nastavení správná nebo ne:

    • i) Název ovládacího prvku TreeView je:TreeView0

    • ii) Zobrazte seznam vlastností Rozbalit vše Příkazové tlačítko a vyberte [Procedura události] v Při kliknutí Vlastnost události.

    • iii) Ujistěte se, že stejné nastavení je neporušené pro Sbalit vše Příkazové tlačítko také.

    • iv) Klikněte na uzel s podřízenými uzly, abyste viděli, zda se při opakovaných kliknutích sbalují nebo rozbalují.

    • v) Pokud je ve formuláři umístěn ovládací prvek ImageList, pak jeho název musí být ImageList1 .

      Pokračujme druhou částí kódu VBA, která implementuje události Drag-Drop.

    Druhá polovina kódu VBA.

  12. Zkopírujte následující druhou část kódu VBA do modulu formuláře frmDragDrop, který implementuje akci Drag-Drop, a vložte ji pod existující kód:

    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

Pro akci Drag-Drop existují čtyři podprogramy, které se provedou automaticky, když přetáhnete uzel(y), zvýrazní uzel, když se přesunete přes jiné uzly, a nakonec jej upustí na jiný uzel nebo na prázdnou oblast na kořenové úrovni. .

Hlavní podprogramy kodexu.

  • TreeView0_OLEStartDrag() - Inicializuje vybranou položku a nastaví uzel na Nic
  • TreeView0_OLEDragOver() - Funguje jako událost pohybu myši, zvýrazní uzel, když nad něj přetáhnete uzel, na cestě k cílovému uzlu.
  • TreeView0_OLEDragDrop() – Provádí kontrolu a ovládání, umísťuje uzly do zrušeného umístění a aktualizuje záznam v základní tabulce.
  • TreeView0_OLECompleteDrag() - Vlastnost DropHighlight je nastavena na Nic.

Pomocí funkce TreeView0_OLEDragDrop() můžeme provádět přetahování Samostatná podprogram. V takovém případě nedojde k žádnému zvýraznění uzlu, když se zdrojový uzel přesune přes jiné uzly, z jednoho místa na druhé, kromě toho, že se ukazatel myši změní na přetažení druhé šipky za něj, jako na ukázkovém obrázku níže. :

Budeme tedy věnovat pozornost tomuto podprogramu a od začátku podrobně zkontrolovat Kód. Na začátku podprogramu jsme deklarovali potřebné Nodes a String Variables a další.

Namísto toho, abych zde opakoval analýzy řádek po řádku, jsem každý řádek/část kódů vhodně okomentoval, abyste pochopili, co to dělá, když si projdete kód. Můžete je projít.

Posloupnost událostí Drop Drop

Pojďme pochopit posloupnost Událostí, Výběr uživatele uzel, přetáhne přes jiné uzly na cestě ke svému konečnému cíli a upustí to na cílovém uzlu. Nebo jej umístěte na prázdnou oblast v ovládacím prvku TreeView, abyste z něj udělali uzel na kořenové úrovni.

Když přetáhnete uzel přes jiný text uzlu, text uzlu se zvýrazní a řekne, že vaše současná pozice je na tomto uzlu na cestě, ať jedete odkudkoli. Když se přesunete z textu uzlu, zvýraznění zmizí. To se děje až k cílovému uzlu. Funkce TreeView0_OLEDragOver() Podprogram se stará o tuto akci zvýraznění.

Když někam pustíte uzel, TreeView0_OLEDragDrop() Podprogram přebíjí. Zde musíme analyzovat záměry uživatele a přijmout vhodná opatření. Následující informace musí být uloženy a analyzovány, aby se uzel přesunul na správné místo.

Důležité informace, které je třeba sledovat.

  1. Reference zdrojového uzlu, hodnoty klíče uzlu a ParentID, podřízené uzly, pokud existují.

  2. Cílový uzel nebo odkaz na umístění, klíč uzlu.

  3. Pokud cíl není uzel, ale prázdná oblast ovládacího prvku TreeView, pak se zdrojový uzel přesune do pozice na kořenové úrovni.

  4. Zdrojový uzel, když je upuštěn na jiný uzel, stane se cílový uzel novým rodičem zdrojového uzlu.

  5. Pokud má zdrojový uzel své vlastní potomky, musí být také přesunuty se svým rodičem.

  6. ** Když je uzel přetažen na jeho vlastní nadřazený uzel, pak tuto akci ignorujte.

    ** Podívejte se například na obrázek výše. Pokud přetáhneme TextBox Uzel a umístěte jej do nadřazeného uzlu Ovládací prvky nebo přetáhněte Ovládací prvky Uzel a umístěte jej do formuláře nadřazeného uzlu pak budou tyto pohyby ignorovány.

  7. ** Pokud Kořenová úroveň Uzel je přetažen do prázdné oblasti, pak nebude provedena žádná akce, protože se již jedná o uzel na kořenové úrovni.

U všech platných přesunů Node musíme aktualizovat ParentID hodnotu pole souvisejícího záznamu na vzorku Tabulka.

Pokles uzlu v prázdné oblasti na kořenové úrovni.

V případě položky číslo 3 výše, musíme vytvořit uzel na kořenové úrovni se stejným ID číslem jako zdrojový uzel, což není povoleno. Duplicitní hodnota klíče není v hierarchii TreeView povolena. Toto je jediná oblast Kodexu, kde je postup, který se tam používá, trochu matoucí.

Postup je uveden níže:

  1. Upravte existující klíč uzlu TreeView přidáním nějakého dalšího textu (řekněme Key X5 změnit na X5Empty ), abyste zabránili konfliktům klíčů při vytváření dočasného uzlu s původním klíčem.

  2. Vytvořte dočasné Uzel s původním klíčem:X5.

  3. Přesuňte všechny podřízené uzly ze zdrojového uzlu, pokud existují, jako podřízené uzly do dočasného uzlu.

  4. Odstraňte zdrojový uzel TreeView pomocí upraveného klíče:X5Empty z ovládacího prvku TreeView, ale související záznam ve vzorové tabulce se nedotkne.

  5. Přesuňte dočasné Uzel s původním klíčem X5 s jeho potomky na kořenovou úroveň ovládacího prvku TreeView.

  6. Aktualizujte pole ParentID souvisejícího záznamu řetězcem nulové délky (“”), abyste jej označili jako uzel na kořenové úrovni.

Vlastní experimenty s přetažením.

Můžete sami vyzkoušet některé experimenty Drag and Drop a uvidíte, jak to funguje. Vyberte uzel, klikněte a podržte levé tlačítko myši, přetáhněte uzel a umístěte jej na jiný uzel, nebo jej pusťte do prázdné oblasti ovládacího prvku TreeView. Když přetáhnete uzel přes jiný text uzlu, zvýrazní se, a když jste mimo uzel, zvýraznění zhasne. Přetažený uzel se objeví na novém místě, kam jste jej upustili. Tento experiment s přetažením můžete zopakovat výběrem jednoho uzlu nebo uzlu s dětmi.

Na základě tohoto pohybu uzlů ParentID souvisejícího záznamu Hodnota pole bude aktualizována pomocí Klíče hodnota (ID) záznamu souvisejícího s cílovým uzlem.

Proč dvoukrokový postup naplnění uzlu?

Nyní se vrátíme k LoadTreeView() Podprogram, abychom se znovu podívali na dvoukrokový proces, který jsme přijali pro naplnění všech uzlů do ovládacího prvku TreeView.

  • Všechny záznamy v Ukázce Tabulky jsou zpočátku přidány jako uzly na kořenové úrovni s použitím hodnoty pole ID jako klíče uzlu.

  • Pokud je ve druhém průchodu záznamů hodnota pole ParentID prázdná, pak tento uzel zůstane jako uzel na kořenové úrovni beze změny.

  • Všechny ostatní záznamy související s uzly s hodnotou ParentID jsou správně přesunuty pod nadřazený uzel.

Přirozeně se nabízí otázka, proč to musíme dělat tímto způsobem?

Uděláme jednoduchý experiment, aby byla odpověď jasná, aniž bychom ji vysvětlovali příliš mnoha slovy. Možná jste již sami provedli několik zkušebních běhů přetažení a přeuspořádali uzly, přičemž v tomto procesu aktualizovali hodnoty ParentID těchto záznamů se změnou. Potřebujeme tedy obnovit hodnoty záznamu do původního stavu v Vzorku Table, než spustíme nové demo.

Již jsme vytvořili kopii naší tabulky Ukázka dříve s názvem Sample_bk jako záloha. Smažte Ukázku Tabulka a vytvořte kopii z Sample_bk s původním názvem:Ukázka .

Otevřete tabulku a zobrazte záznamy a jejich hodnoty pole ParentID. Ukázkový obrázek tabulky je uveden níže:

Hodnoty pole ID jsou automatická čísla a všechny jsou v sekvenčním pořadí a všechny hodnoty ID jsou jedinečné. Následující jednoduché pravidlo řídí přidání podřízeného uzlu do ovládacího prvku TreeView.

Pravidlo jednoduchého podřízeného uzlu: ParentID pole Hodnota (Parent-Key ) v záznamu očekává, že v ovládacím prvku TreeView již existuje nadřazený uzel se stejnou hodnotou jako Key uzlu (ID).

Zkontrolujte třetí záznam shora na obrázku tabulky výše. Hodnota pole ParentID je 2 a ID aktuálního záznamu je 3. V tomto případě bude záznam s ID 2 přidán do ovládacího prvku TreeView, než se pokusíme přidat třetí záznam do uzlu. Oba záznamy nemusí být nutně vedle sebe. Zkontrolujte záznam s ID číslem 21, jeho hodnota pole ParentID je 12, což je menší než aktuální hodnota ID záznamu 21.

V obou případech, když program narazí na ParentID Value v záznamu, předpokládá, že záznam s hodnotou ID rovnou ParentID byl již přidán jako uzel v ovládacím prvku TreeView v dřívějším cyklu naplňování uzlů.

Zdůvodnění postupu ve dvou krocích.

Zkusme nějaké zkušební běhy Drag-Drop. Předtím však máme formulář s názvem frmSample, které které jsme použili v první výukové relaci, a tím jsme načetli všechny uzly TreeView najednou. Ano, doposud jsme postupovali stejnou metodou a od této chvíle potřebujeme nějakou změnu. Předtím však otevřeme starý formulář a uvidíme, jak se uzly objevují ve formuláři.

  1. Otevřete formulář frmSample abyste viděli, jak vypadá zobrazení TreeView se záznamy ukázkové tabulky načtenými pomocí starého pravidla.

  2. Pokud prohlížíte uzly TreeView, zavřete formulář.

  3. Nyní otevřete frmDragDrop Formulář. Připravujeme přetažení uzlu.

  4. Vyberte uzel s tabulkou textu uzlu Klikněte a podržte levé tlačítko myši, přetáhněte jej na uzel pomocí formuláře Node-Text.

  5. Tabulka Uzel s jeho bezprostředními Polemi podřízeného uzlu a jeho podřízené uzly se přesunou jako podřízené uzly pod Formulářem Uzel.

  6. Zavřete formulář frmDragDrop a znovu jej otevřete. Uzly se zobrazí správně tam, kde jste je upustili, jako na obrázku níže.

  7. Nyní zavřete formulář frmDragDrop.

  8. Otevřete formulář frmSample abyste viděli, jak se tato změna objeví na tomto formuláři. Uvítá vás chybová zpráva Element Not Found s číslem chyby:35601.

  9. Vyberte příkazové tlačítko ladění a přejděte na zvýrazněný řádek kódu, kde došlo k chybě.

  10. Ukažte myší na nodKey Parametr metody Add() ukazuje X3, bod myší na ParentKey a zobrazí se X7.

    Když se podíváme na tyto dvě hodnoty parametrů, můžeme předpokládat, že jsme v záznamu s hodnotou ID 3 a pokoušíme se označit tento uzel jako podřízený uzel jinému uzlu, který ještě není obsazen v ovládacím prvku TreeView, s hodnotou ID 7.

  11. Stiskněte F5 Klávesou znovu vyvolejte stejné dialogové okno a klikněte na Konec Příkazové tlačítko pro zastavení programu a zobrazení formuláře v okně databáze. Zavřete formulář frmSample.

  12. Otevřete Ukázku Tabulka pro zobrazení uspořádání čísel ParentID po naší akci přetažení. Záznamy budou vypadat jako na obrázku níže a zvýraznil jsem záznam, který spustil chybu s hodnotou ParentID 7 a zobrazení pozice jeho nadřazeného záznamu.

Po předchozím normálním postupu vyplnění uzlu jsme na třetí pozici záznamu. Protože ParentID zaznamenává hodnotu 7, uzel s hodnotou ID 7 musí být přítomen v ovládacím prvku TreeView. Uzel s hodnotou ID 7 ještě není vyplněno v ovládacím prvku TreeView, ale snažíme se odkazovat na neexistující uzel a to spustí chybu.

I když záznamy seřadíte v pořadí polí ParentID, nové uspořádání záznamů bude vypadat jako na obrázku níže:

Rodičovský uzel jiného záznamu nyní není v očekávané poloze.

Za těchto okolností tedy náš přístup k načítání uzlů TreeView ve dvou krocích funguje jak pro normální akce, tak pro akce po přetažení.

V prvním kroku naplňte všechny záznamy jako kořenové uzly v ovládacím prvku TreeView pomocí hodnoty pole ID jako klíče uzlu.

Nyní jsou všechny uzly všech záznamů dostupné v ovládacím prvku TreeView. Bude snadné je přesunout, kamkoli budeme chtít. Neříká to, že žádný z požadovaných uzlů v TreeView neexistuje.

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 a VBA
  2. Pole objektů třídy VBA MS Access
  3. Základní třída MS-Access a odvozené objekty
  4. VBA Base Class and Derived Object-2
  5. Základní třída a varianty odvozených objektů
  6. Sada záznamů MS-Access a modul třídy
  7. Přístup k modulu třídy a třídám Wrapper
  8. Transformace funkčnosti třídy Wrapper


  1. Extrahujte číslo týdne z data v SQL Server (T-SQL)

  2. Rozdělit oddíl na dva v SQL Server (T-SQL)

  3. Jak nastavím vybranou položku v rozevíracím seznamu

  4. Oprava:Přístup odepřen uživateli ‚root‘@‘localhost‘ v MariaDB