數據模型
class PurchaseNode {
int id;
int parentId; // 0 為根
String name;
List<PurchaseNode> children;
}
遞歸構建樹 (C# WinForm)
void BuildTree(TreeNode parentNode, List<PurchaseNode> allNodes) {
var children = allNodes.Where(n => n.parentId == (int)parentNode.Tag).ToList();
foreach (var child in children) {
TreeNode node = new TreeNode(child.name) { Tag = child.id };
parentNode.Nodes.Add(node);
BuildTree(node, allNodes); // 遞歸
}
}
// 調用
var root = new TreeNode("采購單") { Tag = 0 };
BuildTree(root, allNodes);
treeView1.Nodes.Add(root);
treeView1.ExpandAll();
VB.NET 版本
Sub BuildTree(parentNode As TreeNode, allNodes As List(Of PurchaseNode))
Dim children = allNodes.Where(Function(n) n.parentId = CInt(parentNode.Tag)).ToList()
For Each child In children
Dim node As New TreeNode(child.name) With {.Tag = child.id}
parentNode.Nodes.Add(node)
BuildTree(node, allNodes)
Next
End Sub
數據庫查詢優化
-- 單次查詢所有節點
SELECT id, parent_id, name FROM purchase_order WHERE order_id = @id ORDER BY parent_id, id;
-- C# 端構建查找表
var lookup = allNodes.ToLookup(n => n.parentId); // O(1) 查找子節點
// BuildTree 內部用 lookup[parentId] 替代 Where
大數據懶加載
- TreeNode
Tag 存節點 ID,Nodes.Add(new TreeNode("Loading...")) 佔位。
BeforeExpand 事件中動態查詢子節點並替換佔位節點。
常見問題
| 現象 | 原因 | 解決 |
| 樹不顯示 | 未調用 ExpandAll / 根節點 Tag 不匹配 | 檢查根 parentId=0,調用 ExpandAll() |
| 重複節點 | 數據中存在循環引用 | SQL 加 WHERE 避免循環,或用 HashSet 記錄已訪問 ID |
| 性能差 | 每次遞歸 Where 遍歷全表 | 用 ToLookup/字典預構建父子映射 |