ACC2000: Example Using TreeView Control Drag-and-Drop Capabilities


The information in this article applies to:


 

SUMMARY

Advanced: Requires expert coding, interoperability, and multiuser skills.

This article demonstrates how to use drag-and-drop functionality in the Microsoft TreeView control, version 6.0.

The Microsoft TreeView control, version 6.0 ships with Microsoft Office 2000 Developer.

Microsoft provides programming examples for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This article assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures. Microsoft support professionals can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific needs. If you have limited programming experience, you may want to contact a Microsoft Certified Partner or the Microsoft fee-based consulting line at (800) 936-5200. For more information about Microsoft Certified Partners, please see the following page on the World Wide Web:

http://www.microsoft.com/partner/referral/

For more information about the support options available from Microsoft, please see the following page on the World Wide Web:

http://support.microsoft.com/directory/overview.asp

 

MORE INFORMATION

The Microsoft TreeView control, version 6.0, features built-in drag-and-drop functionality that was not available in earlier versions. It supports drag-and-drop events, such as OLEStartDrag, OLEDragOver, OLECompleteDrag, and OLEDragDrop.

The following example creates a hierarchical list of employees in the Northwind sample database. The TreeView control displays employees according to whom they report to and it enables you to drag employee names to reorder the hierarchy and update the underlying table.

CAUTION: Following the steps in this example will modify the sample database Northwind.mdb. You may want to back up the Northwind.mdb file and perform these steps on a copy of the database.

  1. Start Microsoft Access and open the sample database Northwind.mdb.
  2. Create a new form not based on any table or query in Design view.
  3. On the Insert menu, click ActiveX Control.
  4. In the Insert ActiveX Control dialog box, select Microsoft TreeView Control, version 6.0, then click OK.
  5. Set the following properties for the TreeView control:
6.               Name: xTree
7.               Width: 3"
   Height: 2" 
  1. Double-click the TreeView control and set the following custom properties on the General tab of the TreeCtrl Properties dialog box:
9.               Style: 6 - tvwTreelinesPlusMinusText
10.           LineStyle: 1 - tvwRootLines
11.           OLEDragMode: 1 - ccOLEDragAutomatic
   OLEDropMode: 1 - ccOLEDropManual 
  1. Click OK.
  2. Save the form as TreeViewTest.
  3. On the View menu, click Code.
  4. Type the following procedures:
16.        '==================================================================
17.        'This procedure populates the TreeView control when the form opens.
18.        '==================================================================
19.        Private Sub Form_Load()
20.            On Error GoTo ErrForm_Load
21.         
22.            Dim db As Database
23.            Dim rst As Recordset
24.            Dim nodCurrent As Node, nodRoot As Node
25.            Dim objTree As TreeView
26.            Dim strText As String, bk As String
27.         
28.            Set db = CurrentDb
29.         
30.            'Open the Employees table.
31.            Set rst = db.OpenRecordset("Employees", dbOpenDynaset, dbReadOnly)
32.         
33.            'Create a reference to the TreeView Control.
34.            Set objTree = Me!xTree.Object
35.         
36.            'Find the first employee who is a supervisor.
37.            rst.FindFirst "[ReportsTo] Is Null"
38.         
39.            'Build the TreeView list of supervisors and their employees.
40.            Do Until rst.NoMatch
41.                'Extract the supervisor's name.
42.                strText = rst![LastName] & (", " + rst![FirstName])
43.                'Add a root level node to the tree for the supervisor.
44.                Set nodCurrent = objTree.Nodes.Add(, , "a" & rst!EmployeeID, _
45.                    strText)
46.                'Use a placeholder to save this place in the recordset.
47.                bk = rst.Bookmark
48.                'Run a recursive procedure to add all the child nodes
49.                'for employees who report to this supervisor.
50.                AddChildren nodCurrent, rst
51.                'Return to your placeholder.
52.                rst.Bookmark = bk
53.                'Find the next supervisor.
54.                rst.FindNext "[ReportsTo] Is Null"
55.            Loop
56.         
57.        ExitForm_Load:
58.            Exit Sub
59.         
60.        ErrForm_Load:
61.            MsgBox Err.Description, vbCritical, "Form_Load"
62.            Resume ExitForm_Load
63.        End Sub
64.         
65.        '===================================================================
66.        'This procedure adds child nodes to the tree for all employees who
67.        'report to a particular supervisor, and calls itself recursively
68.        'to add child nodes for all other employees they supervise.
69.        '
70.        'Note that this procedure accepts the open Employees recordset by
71.        'reference so you do not have to open a new recordset for each call.
72.        '===================================================================
73.        Sub AddChildren(nodBoss As Node, rst As Recordset)
74.            On Error GoTo ErrAddChildren
75.         
76.            Dim nodCurrent As Node
77.            Dim objTree As TreeView
78.            Dim strText As String, bk As String
79.         
80.            'Create a reference to the TreeView control.
81.            Set objTree = Me!xTree.Object
82.            'Find the first employee who reports to the supervisor for this node.
83.            rst.FindFirst "[ReportsTo] =" & Mid(nodBoss.Key, 2)
84.            'Build the list of employees who report to this supervisor.
85.            Do Until rst.NoMatch
86.                'Extract the employee's name.
87.                strText = rst![LastName] & (", " + rst![FirstName])
88.                'Add as a child node to the tree.
89.                Set nodCurrent = objTree.Nodes.Add(nodBoss, tvwChild, "a" & _
90.                    rst!EmployeeID, strText)
91.                'Save your place in the recordset.
92.                bk = rst.Bookmark
93.                'Add any employees for whom the current node is a supervisor.
94.                AddChildren nodCurrent, rst
95.                'Return to your place in the recordset and continue to search.
96.                rst.Bookmark = bk
97.                'Find the next employee who reports to this supervisor.
98.                rst.FindNext "[ReportsTo]=" & Mid(nodBoss.Key, 2)
99.            Loop
100.      
101.     ExitAddChildren:
102.         Exit Sub
103.      
104.     ErrAddChildren:
105.         MsgBox "Can't add child:  " & Err.Description, vbCritical, _
106.             "AddChildren(nodBoss As Node) Error:"
107.         Resume ExitAddChildren
108.     End Sub
109.      
110.     '==================================================================
111.     'This procedure in the OLEStartDrag event of the TreeView control
112.     'clears the selected node so you can choose a new one.
113.     '==================================================================
114.     Private Sub xTree_OLEStartDrag(Data As Object, AllowedEffects As _
115.             Long)
116.         Me!xTree.Object.SelectedItem = Nothing
117.     End Sub
118.      
119.     '====================================================================
120.     'Use the OLEDragOver event of the TreeView control to select the
121.     'node to drag, and to highlight the target nodes where the drop will
122.     'occur when you release the mouse. This procedure sets the selected
123.     'node to drag once. After that, if a node is already selected, the
124.     'procedure assumes it was set during an earlier call in the dragging
125.     'process and it does not reset it.  The second half of this procedure
126.     'highlights the node you are dragging over.
127.     '====================================================================
128.     Private Sub xTree_OLEDragOver(Data As Object, Effect As Long, _
129.             Button As Integer, Shift As Integer, x As Single, y As Single, _
130.             State As Integer)
131.         Dim oTree As TreeView
132.      
133.         'Create a reference to the TreeView control.
134.         Set oTree = Me!xTree.Object
135.      
136.         'If no node is selected, select the first node you dragged over.
137.         If oTree.SelectedItem Is Nothing Then
138.             Set oTree.SelectedItem = oTree.HitTest(x, y)
139.         End If
140.      
141.         'Highlight the node being dragged over as a potential drop target.
142.         Set oTree.DropHighlight = oTree.HitTest(x, y)
143.     End Sub
144.      
145.     '==================================================================
146.     'The OLEDragDrop event moves the selected node on the TreeView
147.     'control to its new location and changes the corresponding record in
148.     'the Employees table. The procedure first checks that the TreeView
149.     'has a selected node. If so, it continues to check if a drop target
150.     'node is highlighted. If no node is highlighted, then the user has
151.     'dragged the node off the tree and dropped it into a blank area, and
152.     'the procedure adds a branch to the root of the tree. If a node is
153.     'highlighted, the procedure modifies the Employee table's ReportTo
154.     'field accordingly and sets the selected node's parent property
155.     'to the node that has the drop highlight.
156.     '==================================================================
157.     Private Sub xTree_OLEDragDrop(Data As Object, Effect As Long, _
158.             Button As Integer, Shift As Integer, x As Single, y As Single)
159.         On Error GoTo ErrxTree_OLEDragDrop
160.      
161.         Dim oTree As TreeView
162.         Dim strKey As String, strText As String
163.         Dim nodNew As Node, nodDragged As Node
164.         Dim db As Database
165.         Dim rs As Recordset
166.      
167.         Set db = CurrentDb
168.      
169.         'Open the Employees table for editing.
170.         Set rs = db.OpenRecordset("Employees", dbOpenDynaset)
171.      
172.         'Create a reference to the TreeView control.
173.         Set oTree = Me!xTree.Object
174.      
175.         'If nothing is selected for drag, do nothing.
176.         If oTree.SelectedItem Is Nothing Then
177.         Else
178.             'Reference the selected node as the one being dragged.
179.             Set nodDragged = oTree.SelectedItem
180.             'If the node was dragged to an empty space, update the
181.             'Employees table and make this employee a root node.
182.             If oTree.DropHighlight Is Nothing Then
183.                 'Save the key and the text to use when you re-add the node.
184.                 strKey = nodDragged.Key
185.                 strText = nodDragged.Text
186.                 'Delete the current node for the employee.
187.                 oTree.Nodes.Remove nodDragged.Index
188.                 'Locate the record in the Employees table and update it.
189.                 rs.FindFirst "[EmployeeID]=" & Mid(strKey, 2)
190.                 rs.Edit
191.                 rs![ReportsTo] = Null
192.                 rs.Update
193.                 'Add this employee as a root node.
194.                 Set nodNew = oTree.Nodes.Add(, , strKey, strText)
195.                 'Add all the child nodes for this employee.
196.                 AddChildren nodNew, rs
197.                 'If you are not dropping the node on itself.
198.             ElseIf nodDragged.Index <> oTree.DropHighlight.Index Then
199.                 'Set the drop target as the selected node's parent.
200.                 Set nodDragged.Parent = oTree.DropHighlight
201.                 'Locate the record in the Employees table and update it.
202.                 rs.FindFirst "[EmployeeID]=" & Mid(nodDragged.Key, 2)
203.                 rs.Edit
204.                 rs![ReportsTo] = Mid(oTree.DropHighlight.Key, 2)
205.                 rs.Update
206.             End If
207.         End If
208.      
209.         'Deselect the node
210.         Set nodDragged = Nothing
211.      
212.         'Unhighlight the nodes.
213.         Set oTree.DropHighlight = Nothing
214.      
215.     ExitxTree_OLEDragDrop:
216.         Exit Sub
217.      
218.     ErrxTree_OLEDragDrop:
219.         'If you create a circular branch.
220.         If Err.Number = 35614 Then
221.             MsgBox "A supervisor cannot report to a subordinate.", _
222.                 vbCritical, "Move Cancelled"
223.         Else
224.             MsgBox "An error occurred while trying to move the node.  " & _
225.                 "Please try again." & vbCrLf & Error.Description
226.         End If
227.         Resume ExitxTree_OLEDragDrop
End Sub 
  1. On the Debug menu, click Compile Northwind.
  2. Close the Microsoft Visual Basic Editor and switch the form to Form view. Practice dragging and dropping employee names in the TreeView control and note how both the tree and the Employees table are updated with the new information.

 

REFERENCES

For more information about using the TreeView control, in the Visual Basic Editor, click Microsoft Visual Basic Help on the Help menu, type TreeView control in the Office Assistant or the Answer Wizard, and then click Search to view the topic.

For additional information about the TreeView control, please see the following article in the Microsoft Knowledge Base:

Q162523 Migrating from Data Outline Control to TreeView Control

For more information about using recursion in Microsoft Access, in the Visual Basic Editor, click Microsoft Visual Basic Help on the Help menu, type recursive procedures in the Office Assistant or the Answer Wizard, and then click Search to view the topic.

Additional query words: DragDrop StartDrag DragOver Recursive