Access
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Access

Sắp xếp lại các nút TreeView bằng cách kéo và thả

Giới thiệu.

Tôi hy vọng bạn tìm thấy hướng dẫn tuần trước về ImageCombo Control hữu ích cho các Dự án Microsoft Access của bạn. Với Điều khiển TreeView ImageCombo, chúng tôi có thể tạo một Menu thả xuống đẹp mắt, với một số tùy chọn và chứa nó trong một không gian nhỏ trên biểu mẫu.

Tương tự như vậy, trong một phiên trước đó, chúng ta đã học cách Thêm nút mới ở một vị trí cụ thể trên hệ thống phân cấp nút hoặc Xóa một nút và thêm một nút mới để định vị lại một nút trên Điều khiển chế độ xem dạng cây.

Phương thức này yêu cầu tạo một bản ghi mới trong bảng nguồn cho nút mới. Hoặc xóa một bản ghi hiện có và tạo một bản ghi mới để di chuyển một nút hiện có nhằm biến chúng thành vĩnh viễn. Theo một cách nào đó, với việc sử dụng Chức năng Thêm / Xóa, chúng ta có thể thêm các Nút mới hoặc sắp xếp lại các Nút hiện có trên Điều khiển TreeView. Liên quan đến việc sắp xếp lại các Nút, chúng tôi có một cách tốt hơn để làm điều đó, thay vì xóa các Nút và tạo lại chúng. Kéo Node từ vị trí hiện tại của nó và thả nó vào nơi chúng ta muốn trên TreeView Control. Đây là những gì chúng ta sẽ tìm hiểu trong tập này

Cách tiếp cận đơn giản này chỉ cần cập nhật sự thay đổi của giá trị trường ParentID của các bản ghi liên quan để thay đổi vĩnh viễn.

Các chủ đề được đề cập cho đến nay trong các Phiên trước đó.

  1. Hướng dẫn Điều khiển Microsoft TreeView
  2. Tạo Menu Truy cập với Điều khiển TreeView
  3. Gán hình ảnh cho điều khiển TreeView
  4. Gán hình ảnh cho TreeView Control-2
  5. Kiểm soát TreeView Kiểm tra-Đánh dấu Thêm nút Xóa
  6. Trình đơn truy cập thả xuống TreeView ImageCombo

Tuy nhiên, chúng tôi có thể gặp một số thách thức khi sử dụng phương pháp này và chúng tôi sẽ đến với vấn đề đó sau trong Phiên này.

Bảng và Biểu mẫu Dữ liệu Demo.

Chúng ta cần một Bảng và một Biểu mẫu. Chúng tôi đã có một bảng phù hợp với tên Mẫu được tạo trong một Phiên hướng dẫn trước đó. Nếu bạn đã tải xuống Cơ sở dữ liệu Demo, từ trang liên kết thứ hai được cung cấp ở trên trước đó, thì bạn cũng có thể sử dụng Cơ sở dữ liệu đó cho Phiên này. Chúng tôi sẽ sử dụng các đối tượng sau từ Cơ sở dữ liệu đó cho các thử nghiệm Kéo-Thả của chúng tôi:

  • Bảng: Mẫu
  • Biểu mẫu: frmSample

Hình ảnh điều khiển TreeView trên frmSample với dữ liệu demo được cung cấp bên dưới để tham khảo:

Bạn có thể tải xuống Cơ sở dữ liệu demo ( ProjectMenu.zip ) từ Trang liên kết thứ hai được cung cấp ở trên và trích xuất ProjectMenu.accdb cơ sở dữ liệu.

Biểu mẫu mới để chạy thử kéo thả.

  1. Mở cơ sở dữ liệu ProjectMenu.accdb.

  2. Tạo một bản sao của bảng Mẫu và đặt tên là Sample_bk, giữ nó an toàn, chúng tôi sẽ cần dữ liệu ban đầu của nó mà không cần thay đổi sau này. Khi chúng tôi thử nghiệm với phương pháp kéo-thả, cần phải cập nhật giá trị trường ParentId trên Bảng demo mẫu. Tuy nhiên, chúng tôi cần dữ liệu gốc sau này, nếu không có những thay đổi này.

  3. Tạo Biểu mẫu mới với tên frmDragDrop .

  4. Thiết kế biểu mẫu frmDragDrop sẽ giống như hình dưới đây khi bạn hoàn thành.

  5. Chèn Điều khiển TreeView từ Danh sách điều khiển ActiveX và đặt nó trên biểu mẫu, để lại đủ không gian phía trên điều khiển, để chúng ta có thể tạo hai Nút lệnh và Nhãn tiêu đề phía trên nó. Kéo chốt định cỡ ở góc dưới cùng bên phải để làm cho nó đủ lớn để hiển thị tất cả các Nút mà không cần cuộn.

  6. Thay đổi Tên Giá trị thuộc tính của Điều khiển TreeView thành TreeView0 .

  7. Chèn một nút lệnh ở trên và cạnh trái của Điều khiển TreeView. Thay đổi Tên Giá trị thuộc tính thành cmdExpand Chú thích giá trị thành Mở rộng tất cả .

  8. Chèn Nút lệnh thứ hai ở trên và vào cạnh bên phải của Điều khiển TreeView. Thay đổi Tên Giá trị thuộc tính thành cmdCollapse Chú thích Giá trị thuộc tính để Thu gọn tất cả.
  9. Chèn một Điều khiển Nhãn phía trên các Nút Lệnh, đủ rộng để viết Tiêu đề như được hiển thị ở trên và thay đổi Kích thước Phông chữ 14.

  10. Bỏ qua Điều khiển ImageList, hiện tại, tôi đã nhận xét về các Dòng mã sửa đổi số chỉ mục Node ImageList. Sau đó, bạn có thể Nhập Điều khiển Danh sách Hình ảnh với Hình ảnh được tải lên theo cách thủ công, từ Cơ sở dữ liệu Demo Hướng dẫn trước đó của chúng tôi (từ Trang liên kết thứ 4 được đưa ra ở trên) và sử dụng nó để hiển thị Node-Hình ảnh trên Nodes. Khi các vị trí của Nút được thay đổi trong các hành động Kéo thả, chúng ta cần thay đổi Hình ảnh của Nút cũng tùy thuộc vào vị trí của Nút (Nút cấp gốc hoặc Nút con) trên Điều khiển TreeView.

    Mã Mô-đun Biểu mẫu Kéo-Thả.

  11. Hiển thị Mô-đun mã VBA của Biểu mẫu frmDragDrop, Sao chép và Dán Mã VBA sau (đây chỉ là nửa đầu của Mã mô-đun biểu mẫu) vào Mô-đun lớp của Biểu mẫu frmDragDrop và Lưu Biểu mẫu:

    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

    Tôi biết bạn đã quen thuộc với Mã trên, nếu bạn đã xem qua các Tập trước đó, ngoại trừ LoadTreeView () chương trình con với một số thay đổi. Ở đây, việc điền các Nút TreeView đã được chia thành một quy trình gồm hai bước.

    Tóm lại, đây là những gì sẽ xảy ra trong Chương trình con này.

    • Tất cả các bản ghi trên Mẫu Bảng đã được tải dưới dạng Nút cấp gốc của Điều khiển TreeView, với giá trị trường ID là Khóa, trong bước đầu tiên.

    • Một lần nữa, những bản ghi này đã được đọc lần thứ hai và kiểm tra giá trị trong ParentId , nếu trống thì Nút sẽ được giữ lại làm Nút cấp gốc.

    • Nếu trường ParentID có Giá trị thì xác định Node với giá trị ParentID là Node-Key và di chuyển Nút hiện tại làm Nút con của nó hoặc [ Relative] Tham số (trong số Thêm () Phương pháp ) giá trị được cập nhật.

    • Mặc dù có vẻ như quy trình điền Node hai bước là một bài tập không cần thiết, nhưng có một lý do chính đáng tại sao chúng ta phải làm theo phương pháp này. Chúng tôi sẽ quay lại vấn đề này sau một chút và bạn sẽ biết nó mà không cần giải thích nhiều.

    • Trên Thiết kế của Biểu mẫu, tôi đã đưa ra Điều khiển Danh sách Hình ảnh. Bạn có thể chèn Điều khiển ActiveX của ImageList và tải lên một số hình ảnh trong đó theo cách thủ công từ đĩa hoặc sao chép và dán điều khiển này với các hình ảnh từ Tải xuống Cơ sở dữ liệu Demo trước đó. Trong cả hai trường hợp, hãy đảm bảo rằng tên của điều khiển ImageList là ImageList1 . Nếu không, bạn cần thay đổi tên trong Mã.

    • Sau đó, kích hoạt các dòng được chú thích trong Thủ tục sự kiện Form_Open (). Bật các dòng sau bằng cách xóa biểu tượng chú thích khỏi đầu dòng:

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

    • Trong TreeView0_ OLEDragDrop () Chương trình con (trong phần thứ 2 của Mã VBA) bật Tham số chỉ mục hình ảnh của các nút, bằng cách loại bỏ các ký hiệu Chú thích khỏi các dòng đó. Với những thay đổi này, Hình ảnh nút sẽ xuất hiện trên Điều khiển TreeView. Nếu bạn có Kiểm soát danh sách hình ảnh của riêng mình với Hình ảnh đã tải lên thì hãy thay đổi Số chỉ mục dựa trên Hình ảnh bạn muốn chèn vào các nút.

      TreeView0_NodeClick () Quy trình sự kiện Mở rộng nút hiện tại, nếu các Nút con ở trạng thái thu gọn, nếu không, các Nút con sẽ được Thu gọn. Thông thường, hành động này được kiểm soát (không có Mã) bằng cách nhấp vào +/- Biểu tượng trên dòng cây của nút có nút con.

      Các chương trình con cmdExpand_Click () cmdCollapse_Click () Sự kiện Mở rộng tất cả các Nút và thu gọn tất cả các Nút tương ứng.

      Khi đoạn mã trên chạy, màn hình sẽ giống như Hình ảnh Dạng xem Biểu mẫu được cung cấp bên dưới:

    • Bạn có thể lưu frmDragDrop Tạo và mở nó ở Dạng xem Thường. Nếu mọi thứ diễn ra tốt đẹp thì bạn sẽ thấy màn hình trên. Hãy thử Mở rộng tất cả Thu gọn tất cả Các nút lệnh và kiểm tra xem chúng có đang hoạt động hay không. Nếu không, hãy kiểm tra lại các cài đặt sau đã chính xác hay chưa:

    • i) Tên của Điều khiển TreeView là: TreeView0

    • ii) Hiển thị Trang thuộc tính của Exampand All Nút lệnh và chọn [Thủ tục sự kiện] trong Khi nhấp Thuộc tính sự kiện.

    • iii) Đảm bảo rằng cài đặt tương tự vẫn nguyên vẹn cho Thu gọn tất cả Nút lệnh cũng có.

    • iv) Nhấp vào một nút, có các nút con, để xem liệu chúng thu gọn hay mở rộng khi nhấp chuột lặp lại.

    • v) Nếu ImageList Control được đặt trên Biểu mẫu thì tên của nó phải là ImageList1 .

      Hãy để chúng tôi tiếp tục với phần thứ hai của Mã VBA triển khai Sự kiện kéo-thả.

    Nửa thứ hai của mã VBA.

  12. Sao chép Phần thứ hai sau của Mã VBA, trên Mô-đun biểu mẫu frmDragDrop, thực hiện hành động Kéo-Thả và Dán nó bên dưới Mã hiện có:

    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

Đối với hành động Kéo-Thả, có bốn chương trình con, chúng sẽ tự động thực thi khi bạn Kéo (các) Nút, đánh dấu Nút khi được di chuyển qua các Nút khác và cuối cùng thả nó trên một Nút khác hoặc trên vùng trống cấp Gốc .

Các chương trình con chính của Quy tắc.

  • TreeView0_OLEStartDrag () - Khởi tạo mục đã chọn và đặt Nút thành Không có gì
  • TreeView0_OLEDragOver () - Hoạt động giống như Sự kiện di chuyển chuột, làm nổi bật Nút, khi kéo một Nút phía trên nó, trên đường đến Nút mục tiêu.
  • TreeView0_OLEDragDrop () - Thực hiện kiểm tra và điều khiển, định vị (các) Nút ở Vị trí bị thả và cập nhật bản ghi trên Bảng cơ sở.
  • TreeView0_OLECompleteDrag () - Thuộc tính DropHighlight được đặt thành Không có gì.

Chúng tôi có thể thực hiện các hoạt động Kéo và Thả với TreeView0_OLEDragDrop () Chương trình con một mình. Trong trường hợp đó, sẽ không có bất kỳ Nút nào được tô sáng, khi Nút nguồn di chuyển qua các Nút khác, từ vị trí này sang vị trí khác, ngoại trừ việc Con trỏ chuột chuyển sang kéo mũi tên thứ hai phía sau nó, như trong hình ảnh mẫu bên dưới :

Vì vậy, chúng ta sẽ chú ý đến chương trình con này và kiểm tra Code chi tiết ngay từ đầu. Ở phần đầu của chương trình con, chúng ta đã khai báo các nút và biến chuỗi cần thiết, và những thứ khác.

Thay vì lặp lại các phân tích từng dòng ở đây, tôi đã Nhận xét về từng dòng / phần của mã một cách phù hợp để bạn sẽ hiểu nó có tác dụng gì khi bạn xem qua Mã. Bạn có thể xem qua chúng.

Chuỗi sự kiện thả thính

Hãy để chúng tôi hiểu chuỗi Sự kiện, Người dùng Lựa chọn một nút, Kéo qua các nút khác trên đường đến đích cuối cùng và Giọt nó trên Target Node. Hoặc Thả nó vào vùng trống trên Điều khiển TreeView để biến nó thành Nút cấp gốc.

Khi bạn kéo một Node qua một Node-Text khác, Node-Text sẽ được đánh dấu, cho biết rằng vị trí hiện tại của bạn là trên Node này trên đường đi, cho dù bạn đi bất cứ đâu từ đây. Khi di chuyển ra khỏi Node-text, phần đánh dấu sẽ biến mất. Điều này xảy ra xuyên suốt đến Nút mục tiêu. TreeView0_OLEDragOver () Chương trình con thực hiện hành động đánh dấu này.

Khi bạn thả một nút ở đâu đó, TreeView0_OLEDragDrop () Chương trình con có quá tải. Ở đây, chúng tôi phải phân tích ý định của Người dùng và thực hiện hành động thích hợp. Thông tin sau phải được lưu và phân tích để di chuyển Node đến vị trí chính xác.

Thông tin quan trọng cần theo dõi.

  1. Tham chiếu nút nguồn, Khóa nút và giá trị ParentID, Nút con, nếu có.

  2. Nút đích hoặc tham chiếu vị trí, Khóa nút.

  3. Nếu Mục tiêu không phải là Nút mà là vùng trống của Điều khiển TreeView, thì Nút nguồn sẽ được di chuyển vào vị trí cấp gốc.

  4. Nút nguồn khi được thả trên một nút khác, nút đích sẽ trở thành nút mẹ mới của nút nguồn.

  5. Nếu Source Node có con riêng của nó thì chúng cũng phải được chuyển cùng với Cha mẹ của chúng.

  6. ** Khi Node được kéo và thả trên Parent-Node của chính nó thì Bỏ qua hành động này.

    ** Ví dụ, hãy kiểm tra hình ảnh trên. Nếu chúng tôi kéo TextBox Node và thả nó vào nút mẹ Controls, hoặc kéo Điều khiển Node và thả nó vào Biểu mẫu của nút chính thì những động thái đó sẽ bị bỏ qua.

  7. ** Nếu Cấp gốc Nút được kéo và thả vào vùng trống, sau đó sẽ không có hành động nào được thực hiện vì nó đã là Nút cấp gốc.

Đối với tất cả các lần di chuyển hợp lệ của Node, chúng tôi cần cập nhật ParentID giá trị trường của bản ghi liên quan trên Mẫu Bảng.

Nút Thả vào Vùng trống cấp Gốc.

Trong trường hợp của mục số 3 ở trên, chúng ta phải tạo một Nút cấp gốc, có cùng Số ID của Nút nguồn, điều này không được phép. Giá trị khóa trùng lặp không được phép trong hệ thống phân cấp TreeView. Đây là khu vực duy nhất của Bộ quy tắc, nơi bạn sẽ thấy hơi khó hiểu về quy trình sau đó.

Quy trình như sau:

  1. Sửa đổi Khóa nút TreeView hiện có với việc bổ sung một số văn bản bổ sung, (giả sử Khóa X5 thay đổi tới X5Empty ), để tránh xung đột Khóa trong khi tạo Nút tạm thời với Khóa ban đầu.

  2. Tạo tạm thời Nút với Khóa gốc: X5.

  3. Di chuyển tất cả các Nút con từ Nút nguồn, nếu có, dưới dạng các Nút con sang Nút Tạm thời.

  4. Xóa nút nguồn TreeView bằng Khóa đã sửa đổi: X5Empty từ Điều khiển TreeView , nhưng bản ghi liên quan trên bảng Mẫu không được chạm vào.

  5. Di chuyển tạm thời Nút bằng khóa gốc X5 cùng với con của nó đến vị trí cấp Gốc của Điều khiển TreeView.

  6. Cập nhật trường ParentID của bản ghi liên quan bằng một chuỗi có độ dài bằng 0 (“”) để đánh dấu nó là Nút cấp gốc.

Tự Thử nghiệm Kéo Thả.

Bạn có thể tự mình thử một số thử nghiệm Kéo và Thả và xem nó hoạt động như thế nào. Chọn một Node, nhấp và giữ chuột trái, kéo Node và thả nó trên một Node khác hoặc thả nó vào vùng trống của TreeView Control. Khi bạn kéo Node qua Node-Text khác, nó sẽ được đánh dấu và khi bạn ra khỏi Node, vùng highlight sẽ biến mất. Node được kéo sẽ xuất hiện ở vị trí mới mà bạn đã thả nó xuống. Bạn có thể lặp lại thử nghiệm kéo thả này bằng cách chọn một Nút hoặc Nút có Trẻ em.

Dựa trên chuyển động này của các nút, ParentID của bản ghi liên quan giá trị trường sẽ được cập nhật bằng Khóa giá trị (ID) của bản ghi liên quan đến Nút đích.

Tại sao phải sử dụng quy trình điền nút hai bước?

Bây giờ, chúng ta sẽ quay lại LoadTreeView () Chương trình con, để xem lại quy trình hai bước mà chúng tôi đã áp dụng để đưa tất cả các Nút vào Điều khiển TreeView.

  • Tất cả các bản ghi trong Mẫu Ban đầu, bảng được thêm dưới dạng Nút cấp gốc, sử dụng giá trị trường ID làm Node-Key.

  • Trong lần vượt qua thứ hai của các bản ghi, nếu giá trị trường ParentID trống thì Nút đó sẽ vẫn là Nút cấp gốc mà không có thay đổi.

  • Tất cả các bản ghi liên quan đến Nút khác có Giá trị ParentID đều được di chuyển chính xác dưới Nút mẹ của nó.

Đương nhiên, câu hỏi xuất hiện, tại sao chúng ta phải làm theo cách này?

Chúng tôi sẽ làm một thí nghiệm đơn giản để làm cho câu trả lời rõ ràng mà không cần giải thích nó bằng quá nhiều từ. Bạn có thể đã tự mình thực hiện một số lần chạy thử kéo và thả các lần chạy thử và sắp xếp lại các nút, trong quá trình này đã cập nhật các giá trị ParentID của bản ghi đó với sự thay đổi. Vì vậy, chúng tôi cần đặt lại các giá trị bản ghi về trạng thái ban đầu trong Mẫu Bảng, trước khi chúng tôi bắt đầu một bản trình diễn mới.

Chúng tôi đã tạo một bản sao của Bảng Mẫu của chúng tôi trước đó, với tên Sample_bk như một bản sao lưu . Xóa Mẫu Lập bảng và tạo một bản sao từ Sample_bk với tên ban đầu: Mẫu .

Mở Bảng và xem các bản ghi và Giá trị trường ParentID của chúng. Hình ảnh mẫu của Bảng được đưa ra dưới đây:

Giá trị Trường ID là Số tự động và tất cả chúng đều theo thứ tự tuần tự và tất cả các giá trị Id là duy nhất. Quy tắc đơn giản sau đây điều chỉnh việc thêm Nút con vào Điều khiển TreeView.

Quy tắc nút con đơn giản: ParentID Giá trị trường ( Khóa chính ) trong bản ghi dự kiến ​​rằng Nút mẹ đã tồn tại trong Điều khiển TreeView, có cùng giá trị với Node-Key (ID) .

Kiểm tra bản ghi thứ ba từ trên cùng, trong Hình ảnh Bảng ở trên. Giá trị trường ParentID là 2 và ID của bản ghi hiện tại là 3. Trong trường hợp này, bản ghi có ID 2 sẽ được thêm vào Điều khiển TreeView trước khi chúng tôi cố gắng thêm bản ghi thứ ba vào Node. Cả hai hồ sơ không nhất thiết phải ở cạnh nhau. Kiểm tra bản ghi có ID số 21, giá trị trường ParentID của nó là 12, nhỏ hơn giá trị ID bản ghi hiện tại 21.

Trong cả hai trường hợp, khi chương trình gặp Giá trị ParentID trong một bản ghi, nó sẽ giả định rằng bản ghi có giá trị ID bằng ParentID đã được thêm vào dưới dạng một Nút trong Điều khiển TreeView trong chu kỳ điền các Nút trước đó.

Giải thích cho quy trình hai bước.

Hãy để chúng tôi thử một số lần chạy thử Kéo-Thả. Tuy nhiên, trước đó, chúng tôi có một Biểu mẫu với tên frmSample, cái nào chúng tôi đã sử dụng trong Phiên hướng dẫn đầu tiên và trong đó chúng tôi đã tải tất cả các Nút TreeView trong một lần. Có, chúng tôi đã làm theo cùng một phương pháp cho đến nay và chúng tôi cần một số thay đổi từ bây giờ. Tuy nhiên, trước đó, chúng ta hãy mở biểu mẫu cũ và xem các Nút xuất hiện trên Biểu mẫu như thế nào.

  1. Mở Biểu mẫu frmSample để xem màn hình TreeView trông như thế nào, với các bản ghi bảng Mẫu, được tải bằng quy tắc cũ.

  2. Nếu bạn đang xem các Nút TreeView thì hãy đóng Biểu mẫu.

  3. Bây giờ, hãy mở frmDragDrop Biểu mẫu. Chúng tôi đang chuẩn bị kéo và thả một Node.

  4. Chọn nút với Node-Text Bảng, Nhấp và giữ nút chuột trái, kéo và thả nó trên Node, với Biểu mẫu Node-Text.

  5. Bảng Nút với Trường nút con ngay lập tức của nó và các Nút con của nó được di chuyển dưới dạng Nút con trong Biểu mẫu Nút.

  6. Đóng Biểu mẫu frmDragDrop và mở lại. Các nút sẽ xuất hiện chính xác, nơi bạn đã bỏ chúng, như hình ảnh được đưa ra bên dưới.

  7. Bây giờ, hãy đóng Biểu mẫu frmDragDrop.

  8. Mở Biểu mẫu frmSample để xem thay đổi này xuất hiện như thế nào trên Biểu mẫu này. Bạn sẽ được chào đón bằng một thông báo Lỗi, Không tìm thấy phần tử với Số lỗi:35601.

  9. Chọn Nút lệnh gỡ lỗi để chuyển đến dòng Mã được đánh dấu, nơi xảy ra Lỗi.

  10. Trỏ chuột vào gật đầu Tham số của phương thức Add (), nó hiển thị X3, điểm chuột trên ParentKey và nó hiển thị X7.

    Nhìn vào hai giá trị tham số này, chúng ta có thể giả định rằng chúng ta đang ở trên bản ghi với giá trị ID 3 và đang cố gắng chỉ định Node này làm Node con, cho một Node khác chưa được điền vào TreeView Control, với giá trị ID 7.

  11. Nhấn F5 Phím để hiển thị lại cùng một hộp thoại và Nhấp vào Kết thúc Nút lệnh để dừng Chương trình và hiển thị Biểu mẫu trên Cửa sổ Cơ sở dữ liệu. Đóng Biểu mẫu frmSample.

  12. Mở Mẫu Bảng để xem sự sắp xếp của các Số ParentID, sau hành động kéo và thả của chúng ta. Bản ghi sẽ giống như hình ảnh được cung cấp bên dưới và tôi đã đánh dấu bản ghi đã kích hoạt Lỗi với giá trị ParentID 7 và hiển thị vị trí bản ghi gốc .

Theo quy trình thông thường Node điền trước đó, chúng tôi đang ở vị trí bản ghi thứ ba. Vì, các bản ghi ghi giá trị ParentID 7, Nod có giá trị ID 7 phải có trong Điều khiển TreeView. Nút có giá trị ID 7 chưa được điền vào Điều khiển TreeView, nhưng chúng tôi đang cố gắng tham chiếu đến Nút không tồn tại và điều này gây ra Lỗi.

Ngay cả khi bạn Sắp xếp các bản ghi trong trường ParentID theo thứ tự, sự sắp xếp mới của các bản ghi sẽ giống như hình dưới đây:

Bây giờ, Nút mẹ của bản ghi khác không ở vị trí mong đợi.

Do đó, trong những trường hợp này, phương pháp tải nút TreeView hai bước của chúng tôi cũng hoạt động cho cả hành động bình thường và sau khi kéo thả.

Trong bước đầu tiên, điền tất cả các bản ghi dưới dạng Nút cấp gốc trong Điều khiển TreeView bằng cách sử dụng giá trị trường ID làm Node-Key.

Bây giờ, tất cả các Nút của tất cả các bản ghi đều có sẵn trong Điều khiển TreeView. Sẽ rất dễ dàng để di chuyển chúng đến bất cứ nơi nào chúng ta muốn. It doesn’t say any of the required Node doesn’t exist in the 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. Mô-đun lớp MS-Access và VBA
  2. Mảng đối tượng lớp VBA MS-Access
  3. Lớp cơ sở MS-Access và các đối tượng có nguồn gốc
  4. VBA Base Class and Derived Object-2
  5. Lớp cơ sở và các biến thể đối tượng có nguồn gốc
  6. MS-Access Recordset and Class Module
  7. Truy cập mô-đun lớp và các lớp gói
  8. Chuyển đổi chức năng lớp bao bọc


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách ngành công nghiệp chăm sóc sức khỏe sử dụng cơ sở dữ liệu

  2. Mẹo về Bảng Microsoft Access - Thủ thuật &Nguyên tắc Phần III

  3. VBA Base Class và Derived Object-2

  4. Mẹo cơ sở dữ liệu cho người mới bắt đầu

  5. Access nói chuyện với các nguồn dữ liệu ODBC như thế nào? Phần 6