Access
 sql >> база данни >  >> RDS >> Access

Пренаредете възлите на TreeView чрез плъзгане и пускане

Въведение.

Надявам се, че сте намерили урока от миналата седмица за ImageCombo Control полезен за вашите проекти на Microsoft Access. С TreeView ImageCombo Control бихме могли да създадем красиво падащо меню с няколко опции и да го поставим в малко пространство във формуляра.

По същия начин, в по-ранна сесия, научихме как да добавяме нови възли на определено място в йерархията на възлите или да изтриваме възел и да добавяме нов, за да преместим възел в контролата на дървовидния изглед.

Този метод изисква създаването на нов запис в изходната таблица за новия възел. Или изтрийте съществуващ запис и създайте нов, за да преместите съществуващ възел, за да го направите постоянен. По някакъв начин, с използването на функции за добавяне/изтриване, бихме могли да добавим нови възли или да пренаредим съществуващите възли в контролата TreeView. Що се отнася до пренареждането на възли, имаме по-добър начин да го направим, вместо да изтриваме възли и да ги създаваме отново. Плъзнете възела от текущото му местоположение и го пуснете там, където искаме да бъде в TreeView Control. Това ще научим в този епизод

Този прост подход се нуждае само от актуализиране на промяната на стойността на полето ParentID на свързани записи, за да направи промяната постоянна.

Темите, разгледани досега в по-ранните сесии.

  1. Урок за контрол на Microsoft TreeView
  2. Създаване на меню за достъп с TreeView Control
  3. Присвояване на изображения към TreeView Control
  4. Присвояване на изображения към TreeView Control-2
  5. TreeView Control Маркирайте отметка за добавяне на изтриване на възли
  6. Падащо меню за достъп до TreeView ImageCombo

Но може да се сблъскаме с някои предизвикателства, докато използваме този метод и ще стигнем до това малко по-късно в тази сесия.

Таблица и формуляр с демонстрационни данни.

Нуждаем се от таблица и формуляр. Вече имаме подходяща таблица с имеПроба създадена в по-ранна сесия с урок. Ако вече сте изтеглили Демо базата данни от втората страница с връзка, дадена по-горе, тогава можете да използвате тази база данни и за тази сесия. Ще използваме следните обекти от тази база данни за нашите експерименти с плъзгане:

  • Таблица:Проба
  • Формуляр:frmSample

Контролното изображение на TreeView на frmSample с демонстрационни данни е дадено по-долу за справка:

Можете да изтеглите Демо базата данни (ProjectMenu.zip ) от втората страница с връзка, дадена по-горе, и извлечете ProjectMenu.accdb база данни.

Нов формуляр за пробни стартирания с плъзгане.

  1. Отворете базата данни ProjectMenu.accdb.

  2. Направете копие на таблицата Проба и го наименувайте като Sample_bk, пазете го, ще ни трябват оригиналните му данни без промяна по-късно. Когато експериментираме с метода на плъзгане и пускане, е необходимо да актуализираме стойността на полето ParentId в Примерната демонстрационна таблица. Но оригиналните данни ни трябват по-късно, без тези промени.

  3. Създайте нов формуляр с името frmDragDrop .

  4. Дизайнът на формуляр frmDragDrop ще изглежда като изображението, дадено по-долу, когато приключите с него.

  5. Поставете контролата TreeView от списъка с ActiveX контроли и я поставете във формуляра, оставяйки достатъчно място над контролата, така че да можем да създадем два командни бутона и етикет за заглавие над нея. Плъзнете манипулатора за оразмеряване в долния десен ъгъл, за да го направите достатъчно голям за показване на всички възли, без да превъртате.

  6. Променете Име Стойност на свойството на TreeView Control към TreeView0 .

  7. Поставете команден бутон над и левия ръб на TreeView Control. Променете неговото Име Стойност на свойството до cmdExpand и Надпис стойност на Разгъване на всички .

  8. Вмъкнете втори команден бутон над и в десния край на TreeView Control. Променете неговото Име Стойност на свойството до cmdCollapse и Надпис Стойност на свойството за Свиване на всички
  9. Поставете контрола за етикет над командните бутони, достатъчно широка, за да напишете заглавието, както е показано по-горе, и променете неговия размер на шрифта 14.

  10. Игнорирайте контролата ImageList, за момента коментирах кодовите линии, които променят индексните номера на Node ImageList. По-късно можете да импортирате контрола ImageList с ръчно качени изображения от нашата по-ранна демонстрационна база данни (от 4-та страница с връзки, дадена по-горе) и да го използвате за показване на изображения на възли на възли. Когато позициите на възела се променят по време на действията Drag Drop, ние трябва да променим изображенията на възела също в зависимост от позицията на възела (възел на коренно ниво или възел на дете) в контролата TreeView.

    Код на модула на формуляра с плъзгане.

  11. Покажете кодовия модул на VBA на формуляра frmDragDrop, копирайте и поставете следния VBA код (това е само първата половина от кода на модула на формуляра) в модула за клас на frmDragDrop Form и запазете формуляра:

    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

    Знам, че сте запознати с горния код, ако вече сте преминали през по-ранните епизоди, с изключение на LoadTreeView() подпрограма с някои промени. Тук попълването на TreeView възлите е разделено на процес от две стъпки.

    Накратко, това се случва в тази подпрограма.

    • Всички записи в Проба Таблицата е заредена като възли на коренно ниво на TreeView Control, със стойност на полето ID като ключ, в първата стъпка.

    • Отново, тези записи бяха прочетени за втори път и проверете за стойност в ParentId поле, ако е празно, тогава възелът ще бъде запазен като възел на коренно ниво.

    • Ако полето ParentID има Стойност, тогава идентифицирайте възела със стойността ParentID като Node-Key и преместете текущия възел като негов дъщерен възел или неговия [относителен] Параметър (от Добавяне () Метод) стойността се актуализира.

    • Въпреки че изглежда, че двуетапната процедура за попълване на възли е ненужно упражнение, има добра причина да следваме този метод. Ще се върнем към това малко по-късно и ще го разберете без много обяснения.

    • На дизайна на формуляра съм дал контрола ImageList. Можете да вмъкнете ImageList ActiveX Control и качете някои изображения в него ръчно от диска или копирайте и поставете тази контрола с изображения от по-ранни изтегляния на демонстрационна база данни. И в двата случая, моля, уверете се, че името на контролата ImageList е ImageList1 . В противен случай трябва да промените името в кода.

    • След това активирайте коментираните редове в процедурата за събитие Form_Open(). Активирайте следните редове, като премахнете символа за коментар от началото на реда:

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

    • В TreeView0_ OLEDragDrop() Подпрограмата (във 2-ра част на VBA кода) позволява параметрите на индекса на изображението на възлите, като премахва и символите за коментар от тези редове. С тези промени изображенията на възел ще се появят в контролата TreeView. Ако имате своя собствена контрола ImageList с качени изображения, тогава променете индексните номера въз основа на това какво изображение искате да вмъкнете във възлите.

      TreeView0_NodeClick() Процедура за събитие Разширява текущия възел, ако дъщерните възли са в свито състояние, в противен случай дъщерните възли ще бъдат свити. Обикновено това действие се контролира (без код) чрез щракване върху +/- Символ на дървовидната линия на възела с дъщерни възли.

      Подпрограмите cmdExpand_Click() и cmdCollapse_Click() Събития Разгъва всички възли и съответно свива всички възли.

      Когато горният код се изпълнява, дисплеят изглежда като изображението за изглед на формуляр, дадено по-долу:

    • Можете да запазите frmDragDrop Формуляр и го отворете в нормален изглед. Ако всичко е минало добре, ще видите горния екран. Изпробвайте Разгъване на всички и Свиване на всички Командни бутони и проверете дали и те работят. Ако не, проверете отново дали следните настройки са правилни или не:

    • i) Името на TreeView Control е:TreeView0

    • ii) Показване на листа със свойства на Exampand All Команден бутон и изберете [Процедура за събитие] в При щракване Свойство на събитието.

    • iii) Уверете се, че същата настройка е непокътната за Сгъване на всички Команден бутон също.

    • iv) Щракнете върху възел, който има дъщерни възли, за да видите дали те се свиват или разширяват при многократно щракване.

    • v) Ако контролата ImageList е поставена във формуляра, тогава името му трябва да бъде ImageList1 .

      Нека продължим с втората част от VBA кода, която имплементира събитията с плъзгане и пускане.

    Втората половина на VBA кода.

  12. Копирайте следната втора част от VBA кода в модула frmDragDrop, който изпълнява действието Drag-Drop, и го поставете под съществуващия код:

    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

За действието Drag-Drop има четири подпрограми, те са се изпълнили автоматично, когато плъзнете възела(ите), подчертава възела, когато се премести върху други възли и накрая го пуска на различен възел или в празната зона на коренно ниво .

Основните подпрограми на кода.

  • TreeView0_OLEStartDrag() - Инициализира избрания елемент и задава възела на нищо
  • TreeView0_OLEDragOver() - Работи като събитието Mouse Move, подчертава възела, когато плъзга възел над него, по пътя към целевия възел.
  • TreeView0_OLEDragDrop() – Извършва проверка и контрол, позиционира възела(ите) в изпуснатото местоположение и актуализира записа в основната таблица.
  • TreeView0_OLECompleteDrag() - Свойството DropHighlight е настроено на нищо.

Можем да направим Drag and Drop работи с TreeView0_OLEDragDrop() Само подпрограма. В този случай няма да има открояване на възел, когато изходният възел се движи над други възли, от едно място на друго, освен че показалецът на мишката се променя на плъзгане на втора стрелка зад него, както в примерното изображение, дадено по-долу :

Така че ще обърнем внимание на тази подпрограма и ще проверим подробно кода от самото начало. В началото на подпрограмата сме декларирали необходимите възли и низови променливи и други.

Вместо да повтарям анализите ред по ред тук, коментирах всеки ред/раздел от кодове по подходящ начин, така че да разберете какво прави, когато преминете през Кодекса. Можете да преминете през тях.

Последователността на събитията Drap Drop

Нека разберем последователността на събитията, които потребителят избира възел, плъзга се над други възли по пътя към крайната му дестинация и изпуска го на целевия възел. Или го пуснете върху празната област на TreeView Control, за да го направите възел на коренно ниво.

Когато плъзнете възел върху друг текст на възел, текстът на възел се маркира, казвайки, че текущата ви позиция е на този възел по пътя, където и да отидете оттук. Когато се измести от текста на възела, подчертаването изчезва. Това се случва до целевия възел. TreeView0_OLEDragOver() Подпрограмата се грижи за това действие за подчертаване.

Когато пуснете възел някъде, TreeView0_OLEDragDrop() Подпрограмата поема свръхзареждане. Тук трябва да анализираме намеренията на потребителя и да предприемем съответните действия. Следната информация трябва да бъде запазена и анализирана, за да преместите възела на правилното място.

Важната информация, която трябва да следите.

  1. Препратката към изходния възел, стойностите на ключ на възел и родителски идентификатор, деца на възел, ако има такива.

  2. Справочник за целевия възел или местоположение, ключ на възел.

  3. Ако целта не е възел, а празната област на контролата TreeView, тогава възелът източник трябва да бъде преместен в позиция на основно ниво.

  4. Възелът източник, когато бъде пуснат на друг възел, целевият възел става новият родител на изходния възел.

  5. Ако изходният възел има свои собствени деца, те също трябва да бъдат преместени със своя родител.

  6. ** Когато възелът се плъзне и пусне върху неговия собствен родителски възел, тогава игнорирайте това действие.

    ** Например, проверете изображението по-горе. Ако плъзнем TextBox Възел и го пуснете в неговия родителски възел Контроли, или плъзга Контролите Node и го пуснете на неговия родителски възел Формуляр тогава тези ходове ще бъдат игнорирани.

  7. ** Ако Root-ниво Възелът се плъзга и пуска в празната област, след което няма да се предприемат никакви действия, защото вече е възел на коренно ниво.

За всички валидни движения на Node трябва да актуализираме ParentID стойност на полето на свързания запис в Проба Таблица.

Изпускане на възел в празната област на коренно ниво.

В случай на артикул номер3 по-горе, трябва да създадем възел на коренно ниво, със същия идентификационен номер на изходния възел, което не е разрешено. Дублирана стойност на ключ не е разрешена в йерархията на TreeView. Това е единствената част от Кодекса, където ще откриете малко объркване относно процедурата, следвана там.

Процедурата е както следва:

  1. Променете съществуващия ключ на възел TreeView с добавяне на допълнителен текст (кажете ключ X5 промяна до X5Empty ), за да избегнете конфликти на ключове, докато създавате временен възел с оригиналния ключ.

  2. Създайте временен Възел с оригиналния ключ:X5.

  3. Преместете всички дъщерни възли от изходния възел, ако има такива, като дъщерни възли към временния възел.

  4. Изтрийте изходния възел на TreeView с модифицирания ключ:X5Empty от TreeView Control, но свързаният запис в таблицата с примери не е докоснат.

  5. Преместете временните Възел с оригиналния ключ X5 с неговите деца до позицията на коренно ниво на контролата TreeView.

  6. Актуализирайте полето ParentID на свързания запис с низ с нулева дължина (“”), за да го маркирате като възел на коренно ниво.

Самоексперименти на Drag Drop.

Можете сами да изпробвате някои експерименти с плъзгане и пускане и да видите как работи. Изберете възел, щракнете и задръжте левия бутон на мишката, плъзнете възела и го пуснете върху друг възел или го пуснете в празна област на контролата TreeView. Когато плъзнете възела върху друг възел-текст, той се маркира и когато сте извън възела, акцентът изгасва. Влаченият възел ще се появи на новото място, където сте го пуснали. Можете да повторите този експеримент с плъзгане и пускане, като изберете един възел или възел с деца.

Въз основа на това движение на възлите ParentID на свързания запис стойността на полето ще бъде актуализирана с Ключ стойност (ID) на записа, свързан с целевия възел.

Защо процедура за попълване на възел в две стъпки?

Сега ще се върнем към LoadTreeView() Подпрограма, за да разгледаме отново процеса в две стъпки, който сме приели за попълване на всички възли в TreeView Control.

  • Всички записи в Извадката Първоначално таблицата се добавя като възли на коренно ниво, като се използва стойността на полето ID като възел-ключ.

  • При второто преминаване на записите, ако стойността на полето ParentID е празна, тогава този възел ще остане като възел на коренно ниво, без промяна.

  • Всички други записи, свързани с възли със стойност на ParentID, са правилно преместени под родителския възел.

Естествено възниква въпросът защо трябва да го правим по този начин?

Ще направим прост експеримент, за да направим отговора ясен, без да го обясняваме с твърде много думи. Може би вече сте направили някои пробни пуска на пробни пускания с плъзгане и пускане сами и сте пренаредили възли, като в процеса актуализирате стойностите на ParentID на тези записи с промяната. Така че трябва да нулираме стойностите на записа до първоначалното им състояние в Проба Таблица, преди да започнем нова демонстрация.

Вече създадохме копие на нашата таблица Проба по-рано, с името Sample_bk като резерв. Изтрийте Пробата Таблица и направете копие от Sample_bk с оригиналното име:Проба .

Отворете таблицата и вижте записите и техните стойности на полето ParentID. Примерното изображение на таблицата е дадено по-долу:

Стойностите на полето за идентификатор са автоматични номера и всички те са в последователен ред и всички стойности на идентификатор са уникални. Следното просто правило управлява добавянето на дъщерен възел към контролата TreeView.

Правило за прост дъщерен възел: ParentID Стойност на полето (Родителски ключ ) в запис очаква, че родителски възел вече съществува в TreeView Control, със същата стойност като Node-Key (идентификацията).

Проверете третия запис отгоре, в горното изображение на таблицата. Стойността на полето ParentID е 2, а ID на текущия запис е 3. В този случай записът с ID 2 ще бъде добавен към TreeView Control, преди да се опитаме да добавим третия запис към възела. И двата записа не са непременно един до друг. Проверете записа с идентификационен номер 21, стойността на полето на ParentID е 12, по-малко от текущата стойност на ID на записите 21.

И в двата случая, когато програмата срещне стойността на ParentID в запис, тя приема, че записът със стойност на ID, равна на ParentID, вече е добавен като възел в TreeView Control в по-ранния цикъл на попълване на възлите.

Обосноваване на процедурата в две стъпки.

Нека опитаме някои пробни пускания с плъзгане. Но преди това имаме формуляр с името frmSample, коя използвахме в първата учебна сесия и в нея заредихме всички възли на TreeView наведнъж. Да, досега сме следвали същия метод и отсега нататък се нуждаем от промяна. Но преди това нека отворим стария формуляр и да видим как възлите се появяват във формуляра.

  1. Отворете формуляра frmSample за да видите как изглежда екранът на TreeView със записите на Примерна таблица, заредени с помощта на старото правило.

  2. Ако преглеждате възлите на TreeView, затворете формуляра.

  3. Сега отворете frmDragDrop Формуляр. Подготвяме се да плъзгаме и пускаме възел.

  4. Изберете възела с Таблицата с текст на възел, Щракнете и задръжте левия бутон на мишката, плъзнете го и го пуснете върху възела с формуляра за текст на възел.

  5. Таблицата Възел с неговите непосредствени Полета на дъщерния възел и неговите дъщерни възли се преместват като дъщерни възли под Формуляр Възел.

  6. Затворете формуляра frmDragDrop и го отворете отново. Възлите ще се появят правилно там, където сте ги пуснали, като изображението по-долу.

  7. Сега затворете формуляра frmDragDrop.

  8. Отворете формуляра frmSample за да видите как се появява тази промяна в този формуляр. Ще бъдете посрещнати със съобщение за грешка Елементът не е намерен сНомер на грешка:35601.

  9. Изберете командния бутон за отстраняване на грешки, за да отидете на маркирания ред на кода, където е възникнала грешка.

  10. Насочете мишката върху nodKey Параметър на метода Add(), той показва X3, точка мишката върху ParentKey параметър и той показва X7.

    Разглеждайки тези две стойности на параметъра, можем да предположим, че сме в записа със стойност на идентификатора 3 и се опитваме да обозначим този възел като дъщерен възел, към друг възел, който все още не е попълнен в контролата TreeView, със стойност на ID 7.

  11. Натиснете F5 Натиснете, за да изведете отново същия диалогов прозорец и щракнете върху Край Команден бутон за спиране на програмата и извеждане на формуляра в прозореца на базата данни. Затворете frmSample Form.

  12. Отворете Проба Таблица, за да видите подредбата на номерата на ParentID, след нашето действие с плъзгане и пускане. Записите ще изглеждат като изображението, дадено по-долу и маркирах записа, който е задействал грешката със стойност на ParentID 7 и показва позицията на неговия родителски запис.

Следвайки нормалната процедура за попълване на възел по-рано, ние сме на третата позиция за запис. Тъй като записва стойност на ParentID 7, Nod със стойност на ID 7 трябва да присъства в TreeView Control. Възелът със стойност на ID 7 все още не е попълнено в TreeView Control, но се опитваме да препратим към несъществуващия възел и това задейства грешка.

Дори ако сортирате записите в реда на полето ParentID, новото подреждане на записите ще изглежда като изображението, дадено по-долу:

Сега родителският възел на друг запис не е в очакваната позиция.

Следователно, при тези обстоятелства, нашият двуетапен подход за зареждане на TreeView Nodes работи както за нормални, така и за действия след плъзгане и пускане.

В първата стъпка попълнете всички записи като възли на коренно ниво в TreeView Control, като използвате стойността на полето ID като възел-ключ.

Сега всички възли на всички записи са налични в TreeView Control. Ще бъде лесно да ги преместим, където пожелаем. Не се казва, че някой от необходимия възел не съществува в TreeView.

In the second pass on the same set of records, the records with empty ParentID field values are untouched and allowed to remain as Root-level Nodes. In other cases moves the Node as Child-Node under its Parent Node, by updating the [Relative] Parameter of the Node with the following Statement:

Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)

This is what we do through the second pass on the same set of records. You may do it by resetting the Record Pointer to the first record, by executing rst.MoveFirst before the Do . . . Loop, EOF conditions and rst.MoveNext to access each record as we normally do.

Second Step in Reverse Order.

Or you may do it in reverse order. After populating all records as Root-level Nodes the Record Pointer will be beyond the last record and on the EOF position. You may reset the record pointer to the last record, by executing rst.MoveLast before the Do . . . Loop BOF check, and execute rst.MovePrevious to access each record and move the Nodes correctly under its p arent Node. But, the Nodes may load slightly differently in the placement order of Nodes.

You may try this out yourself with the above-suggested change of Code and see the result.

Download Demo Database


  1. Модул за MS-Access Class и VBA
  2. Обектни масиви от клас VBA на MS-Access
  3. Основен клас на MS-Access и производни обекти
  4. VBA Base Class and Derived Object-2
  5. Варианти на основен клас и производен обект
  6. MS-Access Recordset and Class Module
  7. Достъп до модул за класове и класове за обвивка
  8. Преобразуване на функционалност на класа на обвивката


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да създадете отчет със съветника за отчети в Microsoft Access

  2. Използване на SQL изгледи за добавяне/редактиране на данни в Microsoft Access

  3. 5 необичайни съвета за Microsoft Access за 2020 г

  4. 25 преки пътища на Microsoft Access за спестяване на време в таблици в изглед на лист с данни

  5. 6 забавни факта за Microsoft, които вероятно не знаете!