Access
 sql >> Baza danych >  >> RDS >> Access

Zmień rozmieszczenie węzłów TreeView przez przeciąganie i upuszczanie

Wprowadzenie.

Mam nadzieję, że znalazłeś, samouczek z zeszłego tygodnia na temat ImageCombo Control, przydatny dla twoich projektów Microsoft Access. Dzięki kontrolce TreeView ImageCombo możemy stworzyć piękne menu rozwijane z kilkoma opcjami i umieścić je na małej przestrzeni w formularzu.

Podobnie we wcześniejszej sesji dowiedzieliśmy się, jak dodawać nowe węzły w określonej lokalizacji w hierarchii węzłów lub usuwać węzeł i dodawać nowy, aby przenieść węzeł w kontrolce widoku drzewa.

Ta metoda żąda utworzenia nowego rekordu w tabeli źródłowej dla nowego węzła. Lub usuń istniejący rekord i utwórz nowy, aby przenieść istniejący węzeł i uczynić go trwałym. W pewnym sensie za pomocą funkcji Dodaj/Usuń możemy dodawać nowe węzły lub przestawiać istniejące węzły w kontrolce TreeView. Jeśli chodzi o ponowne rozmieszczenie węzłów, mamy lepszy sposób na zrobienie tego, niż usuwanie węzłów i ponowne ich tworzenie. Przeciągnij węzeł z jego bieżącej lokalizacji i upuść go tam, gdzie chcemy, aby był w kontrolce TreeView. Tego nauczymy się w tym odcinku

To proste podejście wymaga jedynie aktualizacji zmiany wartości pola ParentID powiązanych rekordów, aby zmiana była trwała.

Tematy omówione do tej pory we wcześniejszych sesjach.

  1. Samouczek sterowania Microsoft TreeView
  2. Tworzenie menu dostępu za pomocą TreeView Control
  3. Przypisywanie obrazów do kontrolki TreeView
  4. Przypisywanie obrazów do TreeView Control-2
  5. Kontrola TreeView Zaznacz opcję Dodaj usuń węzły
  6. Rozwijane menu dostępu TreeView ImageCombo

Ale możemy napotkać pewne wyzwania podczas korzystania z tej metody i przejdziemy do tego nieco później w tej sesji.

Tabela i formularz danych demonstracyjnych.

Potrzebujemy tabeli i formularza. Mamy już odpowiednią tabelę o nazwie Próbka utworzone we wcześniejszej sesji samouczka. Jeśli już pobrałeś Demo Bazy Danych z drugiej strony linku podanej powyżej, możesz użyć tej Bazy również dla tej Sesji. W naszych eksperymentach z przeciąganiem i upuszczaniem użyjemy następujących obiektów z tej bazy danych:

  • Tabela:Próbka
  • Formularz:frmPrzykład

Obraz kontrolny TreeView na frmSample z danymi demonstracyjnymi jest podany poniżej w celach informacyjnych:

Możesz pobrać demonstracyjną bazę danych (ProjectMenu.zip ) z drugiej strony linku podanej powyżej i wyodrębnij ProjectMenu.accdb Baza danych.

Nowy formularz dla próbnych przebiegów metodą Drag Drop.

  1. Otwórz bazę danych ProjectMenu.accdb.

  2. Zrób kopię tabeli Próbka i nazwij go jako Sample_bk, zachowaj go w bezpiecznym miejscu, będziemy potrzebować jego oryginalnych danych bez zmian później. Kiedy eksperymentujemy z metodą przeciągnij i upuść, konieczne jest zaktualizowanie wartości pola ParentId w przykładowej tabeli demonstracyjnej. Ale będziemy potrzebować oryginalnych danych później, bez tych zmian.

  3. Utwórz nowy formularz o nazwie frmDragDrop .

  4. Po zakończeniu projekt formularza frmDragDrop będzie wyglądał jak obrazek podany poniżej.

  5. Wstaw kontrolkę TreeView z listy kontrolek ActiveX i umieść ją w formularzu, pozostawiając wystarczająco dużo miejsca nad kontrolką, abyśmy mogli utworzyć dwa przyciski poleceń i etykietę nagłówka nad nią. Przeciągnij uchwyt zmiany rozmiaru w prawym dolnym rogu, aby był wystarczająco duży, aby wyświetlić wszystkie węzły bez przewijania.

  6. Zmień Nazwę Wartość właściwości TreeView Control do TreeView0 .

  7. Wstaw przycisk polecenia powyżej i lewej krawędzi kontrolki TreeView. Zmień jego nazwę Wartość właściwości do cmdExpand i Podpis wartość Rozwiń wszystko .

  8. Wstaw drugi przycisk polecenia powyżej i do prawej krawędzi kontrolki TreeView. Zmień jego nazwę Wartość właściwości do cmdCollapse i Podpis Wartość właściwości do Zwiń wszystko.
  9. Wstaw kontrolkę etykiety nad przyciskami poleceń, wystarczająco szeroką, aby napisać nagłówek, jak pokazano powyżej, i zmień jej rozmiar czcionki 14.

  10. Zignoruj ​​kontrolkę ImageList, na razie skomentowałem linie kodu, które modyfikują numery indeksu Node ImageList. Później możesz zaimportować kontrolkę ImageList z ręcznie załadowanymi obrazami z naszej wcześniejszej bazy danych demonstracji samouczka (z czwartej strony łącza podanej powyżej) i użyć jej do wyświetlenia obrazów węzłów na węzłach. Gdy pozycje węzłów są zmieniane podczas akcji Drag Drop, musimy zmienić obrazy węzłów również w zależności od pozycji węzła (węzeł na poziomie głównym lub węzeł podrzędny) w kontrolce TreeView.

    Kod modułu przeciągnij i upuść.

  11. Wyświetl moduł kodu VBA formularza frmDragDrop, skopiuj i wklej następujący kod VBA (jest to tylko pierwsza połowa kodu modułu formularza) do modułu klasy formularza frmDragDrop i zapisz formularz:

    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

    Wiem, że znasz powyższy kod, jeśli przeszedłeś już przez wcześniejsze odcinki, z wyjątkiem LoadTreeView() podprogram z pewnymi zmianami. Tutaj wypełnianie węzłów TreeView zostało podzielone na dwuetapowy proces.

    Krótko mówiąc, tak się dzieje w tym podprogramie.

    • Wszystkie rekordy w Próbka Tabela została załadowana jako węzły poziomu głównego kontrolki TreeView, z wartością pola ID jako kluczem, w pierwszym kroku.

    • Ponownie te rekordy zostały odczytane po raz drugi i sprawdź wartość w Identyfikator rodzica pole, jeśli jest puste, węzeł zostanie zachowany jako węzeł na poziomie głównym.

    • Jeśli pole ParentID ma wartość, zidentyfikuj węzeł z wartością ParentID jako kluczem węzła i przenieś bieżący węzeł jako jego węzeł podrzędny lub jego [względny] Parametr (z Dodaj () Metoda) wartość zostanie zaktualizowana.

    • Chociaż wydaje się, że dwuetapowa procedura wypełniania węzłów jest niepotrzebnym ćwiczeniem, istnieje dobry powód, dla którego musimy zastosować tę metodę. Wrócimy do tego nieco później i będziesz o tym wiedział bez większego wyjaśniania.

    • W projekcie formularza podałem kontrolkę ImageList. Możesz wstawić kontrolkę ImageList ActiveX i prześlij do niego ręcznie niektóre obrazy z dysku lub skopiuj i wklej ten element sterujący za pomocą obrazów z wcześniejszych pobrań bazy danych demonstracyjnych. W obu przypadkach upewnij się, że nazwa kontrolki ImageList to ImageList1 . W przeciwnym razie musisz zmienić nazwę w kodzie.

    • Następnie włącz zakomentowane wiersze w procedurze zdarzenia Form_Open(). Włącz następujące wiersze, usuwając symbol komentarza z początku wiersza:

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

    • W TreeView0_ OLEDragDrop() Podprogram (w drugiej części kodu VBA) włącza parametry indeksu obrazów węzłów, usuwając również symbole komentarza z tych wierszy. Po tych zmianach obrazy węzłów pojawią się w kontrolce TreeView. Jeśli masz własną kontrolkę ImageList z przesłanymi obrazami, zmień numery indeksu w oparciu o obraz, który chcesz wstawić do węzłów.

      TreeView0_NodeClick() Procedura zdarzenia Rozwija bieżący węzeł, jeśli węzły podrzędne są w stanie zwiniętym, w przeciwnym razie węzły podrzędne zostaną zwinięte. Zwykle ta czynność jest kontrolowana (bez kodu), klikając +/- Symbol na linii drzewa węzła z węzłami podrzędnymi.

      Podprogramy cmdExpand_Click() i cmdCollapse_Click() Zdarzenia odpowiednio rozwija wszystkie węzły i zwija wszystkie węzły.

      Gdy powyższy kod zostanie uruchomiony, wyświetlacz wygląda jak obraz widoku formularza podany poniżej:

    • Możesz zapisać frmDragDrop Formularz i otwórz go w widoku normalnym. Jeśli wszystko poszło dobrze, zobaczysz powyższy ekran. Wypróbuj Rozwiń wszystko i Zwiń wszystko Przyciski poleceń i sprawdź, czy też działają. Jeśli nie, sprawdź ponownie, czy następujące ustawienia są poprawne, czy nie:

    • i) Nazwa kontrolki TreeView to:TreeView0

    • ii) Wyświetl arkusz właściwości Exampand All Przycisk polecenia i wybierz [Procedura zdarzenia] w Po kliknięciu Obiekt wydarzenia.

    • iii) Upewnij się, że to samo ustawienie jest nienaruszone dla opcji Zwiń wszystko Przycisk polecenia również.

    • iv) Kliknij węzeł mający węzły podrzędne, aby zobaczyć, czy zwijają się lub rozwijają po wielokrotnych kliknięciach.

    • v) Jeśli kontrolka ImageList jest umieszczona w formularzu, jej nazwa musi mieć postać ImageList1 .

      Przejdźmy do drugiej części kodu VBA, która implementuje zdarzenia przeciągnij i upuść.

    Druga połowa kodu VBA.

  12. Skopiuj następującą drugą część kodu VBA z modułu frmDragDrop Form, który implementuje akcję przeciągnij i upuść, i wklej ją poniżej istniejącego kodu:

    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

W przypadku akcji „przeciągnij i upuść” istnieją cztery podprogramy, które są wykonywane automatycznie po przeciągnięciu węzłów, podświetlają węzeł po przeniesieniu na inne węzły i ostatecznie upuszczają go na inny węzeł lub na pusty obszar poziomu głównego .

Główne podprogramy kodu.

  • TreeView0_OLEStartDrag() - Inicjuje wybrany element i ustawia węzeł na Nic
  • TreeView0_OLEDragOver() — Działa jak zdarzenie ruchu myszy, podświetla węzeł, gdy przeciąga węzeł nad niego, w drodze do węzła docelowego.
  • TreeView0_OLEDragDrop() – Wykonuje kontrolę i kontrole, umieszcza węzły w porzuconej lokalizacji i aktualizuje rekord w tabeli bazowej.
  • TreeView0_OLECompleteDrag() - Właściwość DropHighlight jest ustawiona na Nic.

Możemy wykonać operację przeciągania i upuszczania za pomocą TreeView0_OLEDragDrop() Sam podprogram. W takim przypadku nie będzie żadnego podświetlenia węzła, gdy węzeł źródłowy przesunie się nad inne węzły, z jednego miejsca do drugiego, z wyjątkiem tego, że wskaźnik myszy zmieni się w przeciąganie za nim drugiej strzałki, jak na przykładowym obrazie podanym poniżej :

Zwrócimy więc uwagę na ten podprogram i od samego początku szczegółowo sprawdzimy Kodeks. Na początku podprogramu zadeklarowaliśmy niezbędne węzły, zmienne łańcuchowe i inne.

Zamiast powtarzać tutaj analizę linijka po linijce, odpowiednio skomentowałem każdy wiersz/sekcję kodu, abyście zrozumieli, co robi, gdy będziecie przechodzić przez Kodeks. Możesz je przejrzeć.

Sekwencja zdarzeń Drap Drop

Pozwól nam zrozumieć sekwencję zdarzeń, użytkownik wybiera węzeł, przeciąga się nad innymi węzłami w drodze do miejsca docelowego i upuszcza go w węźle docelowym. Lub upuść go w pustym obszarze kontrolki TreeView, aby uczynić go węzłem na poziomie głównym.

Kiedy przeciągasz węzeł nad innym tekstem węzła, tekst węzła zostaje podświetlony, mówiąc, że twoja aktualna pozycja znajduje się na tym węźle po drodze, gdziekolwiek się stąd wybierasz. Po przeniesieniu z tekstu węzła podświetlenie znika. Dzieje się tak aż do węzła docelowego. TreeView0_OLEDragOver() Subroutine zajmuje się tym podświetlaniem.

Kiedy upuszczasz węzeł gdzieś, TreeView0_OLEDragDrop() Podprogram przejmuje przeciążenie. Tutaj musimy przeanalizować intencje Użytkownika i podjąć odpowiednie działania. Aby przenieść węzeł do właściwej lokalizacji, należy zapisać i przeanalizować następujące informacje.

Ważne informacje do śledzenia.

  1. Referencja węzła źródłowego, wartości klucza węzła i identyfikatora rodzica, elementy podrzędne węzła, jeśli istnieją.

  2. Odniesienie do węzła docelowego lub lokalizacji, klucz węzła.

  3. Jeśli obiekt docelowy nie jest węzłem, ale pustym obszarem kontrolki TreeView, wówczas węzeł źródłowy, który ma zostać przeniesiony do pozycji głównej.

  4. Węzeł źródłowy po upuszczeniu na inny węzeł, węzeł docelowy staje się nowym rodzicem węzła źródłowego.

  5. Jeśli węzeł źródłowy ma własne elementy potomne, muszą one również zostać przeniesione wraz z rodzicem.

  6. ** Kiedy węzeł jest przeciągany i upuszczany na jego własny węzeł nadrzędny, zignoruj ​​tę akcję.

    ** Na przykład sprawdź powyższy obrazek. Jeśli przeciągniemy Pole tekstowe Node i upuść go do jego węzła nadrzędnego Controls, lub przeciąga Elementy sterujące Node i upuść go na jego Formularzu węzła nadrzędnego wtedy te ruchy zostaną zignorowane.

  7. ** Jeśli poziom główny Węzeł jest przeciągany i upuszczany do pustego obszaru, a następnie nie zostanie podjęta żadna akcja, ponieważ jest już węzłem głównym.

W przypadku wszystkich prawidłowych ruchów węzła musimy zaktualizować Identyfikator rodzica wartość pola powiązanego rekordu w Próbce Tabela.

Upuszczenie węzła w pustym obszarze poziomu głównego.

W przypadku pozycji nr 3 powyżej, musimy utworzyć węzeł na poziomie root, z tym samym numerem identyfikacyjnym węzła źródłowego, co jest niedozwolone. Zduplikowana wartość klucza nie jest dozwolona w hierarchii TreeView. Jest to jedyny obszar Kodeksu, w którym można znaleźć trochę zamieszania w stosowanej tam procedurze.

Procedura jest jak poniżej:

  1. Zmodyfikuj istniejący klucz węzła TreeView, dodając dodatkowy tekst (np. Klucz X5 zmień do X5Pusty ), aby uniknąć konfliktów kluczy podczas tworzenia tymczasowego węzła z oryginalnym kluczem.

  2. Utwórz tymczasowy Węzeł z oryginalnym kluczem:X5.

  3. Przenieś wszystkie węzły podrzędne z węzła źródłowego, jeśli takie istnieją, jako węzły podrzędne do węzła tymczasowego.

  4. Usuń węzeł źródłowy TreeView za pomocą zmodyfikowanego klucza:X5Empty z kontrolki TreeView, ale powiązany rekord w tabeli Sample nie jest dotykany.

  5. Przenieś tymczasowe Węzeł z oryginalnym kluczem X5 z jego dziećmi do pozycji Root kontrolki TreeView.

  6. Zaktualizuj pole ParentID powiązanego rekordu ciągiem o zerowej długości („”), aby oznaczyć go jako węzeł na poziomie głównym.

Eksperymenty z przeciąganiem upuszczania.

Możesz samodzielnie wypróbować kilka eksperymentów typu „przeciągnij i upuść” i zobaczyć, jak to działa. Wybierz węzeł, kliknij i przytrzymaj lewy przycisk myszy, przeciągnij węzeł i upuść go na innym węźle lub upuść w pustym obszarze kontrolki TreeView. Kiedy przeciągasz węzeł nad innym tekstem węzła, jest on podświetlany, a kiedy jesteś poza węzłem, podświetlenie gaśnie. Przeciągnięty węzeł pojawi się w nowej lokalizacji, w której go upuściłeś. Możesz powtórzyć ten eksperyment z przeciąganiem i upuszczaniem, wybierając pojedynczy węzeł lub węzeł z dziećmi.

Na podstawie tego ruchu węzłów Identyfikator rodzica powiązanego rekordu wartość pola zostanie zaktualizowana za pomocą klucza wartość (ID) rekordu związanego z węzłem docelowym.

Dlaczego dwuetapowa procedura wypełniania węzłów?

Teraz wrócimy do LoadTreeView() Podprogram, aby przyjrzeć się po raz drugi dwuetapowemu procesowi, który przyjęliśmy do wypełniania wszystkich węzłów w kontrolce TreeView.

  • Wszystkie rekordy w Próbce Tabele są początkowo dodawane jako węzły na poziomie głównym, przy użyciu wartości pola ID jako klucza węzła.

  • W drugim przebiegu rekordów, jeśli wartość pola ParentID jest pusta, wtedy ten węzeł pozostanie jako węzeł na poziomie głównym, bez zmian.

  • Wszystkie inne rekordy związane z węzłami z wartością ParentID są prawidłowo przenoszone pod węzłem nadrzędnym.

Naturalnie pojawia się pytanie, dlaczego musimy to robić w ten sposób?

Zrobimy prosty eksperyment, aby odpowiedź była jasna, bez wyjaśniania jej zbyt wieloma słowami. Być może wykonałeś już kilka próbnych uruchomień próbnych przeciągania i upuszczania samodzielnie i zmieniłeś węzły, w trakcie których zaktualizowałeś wartości ParentID tych rekordów wraz ze zmianą. Dlatego musimy zresetować wartości rekordów do ich pierwotnego stanu w Próbce Tabela, zanim zaczniemy nowe demo.

Stworzyliśmy już kopię naszej tabeli Próbka wcześniej o nazwie Sample_bk jako kopia zapasowa. Usuń Próbkę Złóż tabelę i zrób kopię z Sample_bk o oryginalnej nazwie:Próbka .

Otwórz tabelę i przejrzyj rekordy oraz ich wartości w polu ParentID. Przykładowy obraz tabeli znajduje się poniżej:

Wartości pola identyfikatora to Autonumerowanie i wszystkie są w kolejności sekwencyjnej, a wszystkie wartości identyfikatora są unikatowe. Poniższa prosta reguła reguluje dodawanie węzła podrzędnego do kontrolki TreeView.

Prosta reguła węzła podrzędnego: Identyfikator rodzica pole Wartość (klucz nadrzędny ) w rekordzie oczekuje, że węzeł nadrzędny już istnieje w kontrolce TreeView z taką samą wartością jak Node-Key (identyfikator).

Sprawdź trzeci rekord od góry, w powyższym Table Image. Wartość pola ParentID wynosi 2, a identyfikator bieżącego rekordu to 3. W tym przypadku rekord o identyfikatorze 2 zostanie dodany do kontrolki TreeView przed próbą dodania trzeciego rekordu do węzła. Obie płyty niekoniecznie są obok siebie. Sprawdź rekord o numerze ID 21, jego wartość pola ParentID wynosi 12, mniej niż aktualna wartość ID rekordu 21.

W obu przypadkach, gdy program napotka wartość ParentID w rekordzie, zakłada, że ​​rekord z wartością ID równą ParentID został już dodany jako węzeł w kontrolce TreeView we wcześniejszym cyklu zapełniania węzłów.

Uzasadnienie dwuetapowej procedury.

Wypróbujmy kilka próbnych wersji Drag-Drop. Ale wcześniej mamy formularz o nazwie frmSample, który wykorzystaliśmy w pierwszej sesji samouczka i za jednym razem załadowaliśmy wszystkie węzły TreeView. Tak, do tej pory stosowaliśmy tę samą metodę i od teraz potrzebujemy pewnej zmiany. Ale wcześniej otwórzmy stary formularz i zobaczmy, jak węzły pojawiają się na formularzu.

  1. Otwórz formularz frmSample aby zobaczyć, jak wygląda wyświetlanie TreeView, z rekordami tabeli próbek załadowanymi przy użyciu starej reguły.

  2. Jeśli przeglądasz węzły TreeView, zamknij formularz.

  3. Teraz otwórz frmDragDrop Formularz. Przygotowujemy się do przeciągania i upuszczania węzła.

  4. Wybierz węzeł z Tabelą tekstu węzła, Kliknij i przytrzymaj lewy przycisk myszy, przeciągnij i upuść na węźle za pomocą Formularza tekstu węzła.

  5. Tabela Węzeł z bezpośrednimi polami węzła podrzędnego a jego węzły podrzędne są przenoszone jako węzły podrzędne pod Formularzem Węzeł.

  6. Zamknij formularz frmDragDrop i otwórz go ponownie. Węzły pojawią się poprawnie tam, gdzie je upuściłeś, jak na poniższym obrazku.

  7. Teraz zamknij formularz frmDragDrop.

  8. Otwórz formularz frmSample aby zobaczyć, jak ta zmiana pojawia się w tym formularzu. Zostaniesz powitany komunikatem o błędzie Nie znaleziono elementu z Numerem błędu:35601.

  9. Wybierz przycisk polecenia debugowania, aby przejść do podświetlonej linii kodu, w której wystąpił błąd.

  10. Wskaż myszką nodKey Parametr metody Add() pokazuje X3, punkt mysz na ParentKey i pokazuje X7.

    Patrząc na te dwie wartości parametrów, możemy założyć, że znajdujemy się w rekordzie z identyfikatorem o wartości 3 i próbujemy wyznaczyć ten węzeł jako węzeł podrzędny, do innego węzła, który nie został jeszcze wprowadzony do kontrolki TreeView, z identyfikatorem o wartości 7.

  11. Naciśnij F5 Klawisz, aby ponownie wyświetlić to samo okno dialogowe i kliknij Zakończ Przycisk polecenia, aby zatrzymać program i wyświetlić formularz w oknie bazy danych. Zamknij frmSample Form.

  12. Otwórz Próbkę Tabela, aby zobaczyć rozmieszczenie numerów ParentID, po naszej akcji przeciągnij i upuść. Rekordy będą wyglądać jak obrazek podany poniżej, a ja podświetliłem rekord, który wywołał błąd z wartością ParentID 7 i pokazuje swoją pozycję w rekordzie nadrzędnym.

Zgodnie z wcześniejszą normalną procedurą zapełniania węzłów, jesteśmy na trzecim miejscu rekordu. Ponieważ rekordy ParentID mają wartość 7, a Nod z wartością ID 7 musi być obecny w kontrolce TreeView. Węzeł o wartości identyfikatora 7 nie jest jeszcze umieszczony w kontrolce TreeView, ale próbujemy odwołać się do nieistniejącego węzła, co wywołuje błąd.

Nawet jeśli posortujesz rekordy w polu ParentID, kolejność rekordów będzie wyglądała jak na poniższym obrazku:

Teraz węzeł nadrzędny innego rekordu nie znajduje się w oczekiwanej pozycji.

W związku z tym w tych okolicznościach nasze dwuetapowe podejście do ładowania węzłów TreeView działa zarówno w przypadku akcji zwykłych, jak i po przeciąganiu i upuszczaniu.

W pierwszym kroku wypełnij wszystkie rekordy jako węzły poziomu głównego w kontrolce TreeView, używając wartości pola ID jako klucza węzła.

Teraz wszystkie węzły wszystkich rekordów są dostępne w kontrolce TreeView. Łatwo będzie je przenosić, gdzie tylko zechcemy. Nie mówi, że żaden z wymaganych węzłów nie istnieje w 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 pozycja. 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. Moduł klasy MS-Access i VBA
  2. Tablice obiektów klasy MS-Access VBA
  3. Klasa bazowa MS-Access i obiekty pochodne
  4. VBA Base Class and Derived Object-2
  5. Warianty klasy bazowej i obiektów pochodnych
  6. MS-Access Recordset and Class Module
  7. Dostęp do modułu klas i klas opakowujących
  8. Transformacja funkcjonalności klasy opakowującej


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ROZWIĄZANE:Microsoft Office 365 w wersji 2009 może uszkodzić aplikację bazy danych

  2. Jak bazy danych są wykorzystywane w e-commerce

  3. Dziesięć sposobów, w jakie Twój projekt danych może się nie powieść

  4. Jak program Access komunikuje się ze źródłami danych ODBC? Część 4

  5. Jak zmienić rozmiar kontrolek formularza w programie Access 2016