在开发应用程序时,经常需要展示层次结构的数据,例如文件系统、组织结构等。在这些情况下,树形控件(TreeView)是一个非常有用的界面元素。然而,当数据量较大时,一次性加载所有节点可能会导致性能问题。为了解决这个问题,可以采用“按需加载”(load on demand)的方法,即在用户点击节点时才加载其子节点。本文将介绍一种实现这一功能的高效方法。
在互联网上,可以找到许多关于如何使用递归算法填充树形控件的示例。虽然这些方法很酷,但它们可能不适合需要处理大量数据的应用。在这种情况下,需要一种更轻量级、更快速的方法。本文介绍的方法正是为了满足这一需求。
为了表示层次关系,可以使用如下的数据库表结构:
RecordID (Primary Key) | ParentID | Name
1 | 0 | Topic 1
2 | 0 | Topic 2
3 | 1 | RE: Topic 1
4 | 1 | RE: Topic 1
5 | 2 | RE: RE: Topic 1
6 | 2 | RE: RE: Topic 1
这种表结构可以很好地表示父子关系,并且可以方便地进行拖放操作。
以下代码片段展示了如何使用ADO.NET来动态填充树形控件的节点。请注意,这些代码片段不能直接编译,它们仅用于演示方法。
首先,需要打开一个数据库查询,用于初始化树形控件的根节点或填充选中节点的子节点。然后,可以使用IEnumerator对象来迭代记录并填充TreeView节点。
Public Function GetRootFolders() As IEnumerator
Dim dbCommandObject As SqlCommand
' specify command text and parameters, open the connection, etc.
Dim dR As SqlDataReader = dbCommandObject.ExecuteReader()
If Not dR Is Nothing AndAlso Not dR.IsClosed Then
Return dR.GetEnumerator()
End If
Return Nothing
End Function
接下来,可以这样填充根节点:
Private Sub RefreshTree()
treeView.Nodes.Clear()
Dim iE As IEnumerator = GetRootFolders()
Do While iE.MoveNext()
If iE.Current IsNot Nothing Then
Dim r As DbDataRecord = CType(iE.Current, DbDataRecord)
treeView.Nodes.Add(r("Folder_ID").ToString, _
r("DisplayText").ToString, "folderclose", "folderopen")
End If
Loop
dR.Close()
' add children of root nodes
If treeMain.Nodes.Count > 0 Then
For Each nd As TreeNode In treeMain.Nodes
iE = pDB.GetChildFolders(CInt(nd.Name))
Do While iE.MoveNext()
If iE.Current IsNot Nothing Then
Dim r As DbDataRecord = CType(iE.Current, DbDataRecord)
If Not nd.Nodes.ContainsKey(r("Folder_ID").ToString) Then
nd.Nodes.Add(r("Folder_ID").ToString, _
r("DisplayText").ToString, "folderclose", "folderopen")
End If
End If
Loop
dR.Close()
Next
End If
End Sub
在这段代码中,首先清除了TreeView的现有节点,然后使用GetRootFolders方法获取根节点的记录。对于每条记录,创建一个新的TreeNode并添加到TreeView中。然后,为每个根节点添加其子节点。
当用户点击一个节点时,需要为其添加子节点。以下是处理节点点击事件的代码:
Private Sub treeView_NodeMouseClick(ByVal sender As Object, _
ByVal e As TreeNodeMouseClickEventArgs) Handles treeView.NodeMouseClick
Dim iE As IEnumerator
' add the children of the children just added
If e.Node.Nodes.Count > 0 Then
For Each nd As TreeNode In e.Node.Nodes
iE = GetChildFolders(CInt(nd.Name))
Do While iE.MoveNext()
If iE.Current IsNot Nothing Then
Dim r As DbDataRecord = CType(iE.Current, DbDataRecord)
If Not nd.Nodes.ContainsKey(r("Folder_ID").ToString) Then
nd.Nodes.Add(r("Folder_ID").ToString, _
r("DisplayText").ToString, "folderclose", "folderopen")
End If
End If
Loop
dR.Close()
Next
End If
End Sub