首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# TreeView 建立多層級樹狀目錄完整實作:資料庫設計與遞迴載入

     編輯:關於C語言

資料庫設計:無限級分類表


CREATE TABLE BBS_BestArticleFolder (
    FolderID        INT PRIMARY KEY IDENTITY,
    ParentFolderID  INT NOT NULL DEFAULT 0,  -- 0 表示根節點
    FolderName      NVARCHAR(80) NOT NULL,
    BoardID         INT NOT NULL DEFAULT 0,
    CreaterUserID   INT NOT NULL DEFAULT 0,
    AddTime         DATETIME NOT NULL DEFAULT GETDATE()
);

CREATE INDEX IX_ParentFolderID ON BBS_BestArticleFolder(ParentFolderID);

資料存取層:一次性載入所有節點


public DataView GetFolderDataView(int boardId)
{
    // 假設使用參數化查詢取得該版面所有資料夾
    string sql = "SELECT FolderID, FolderName, ParentFolderID FROM BBS_BestArticleFolder WHERE BoardID = @BoardID";
    var dt = new DataTable();
    using (var conn = new SqlConnection(_connStr))
    using (var cmd = new SqlCommand(sql, conn))
    using (var adapter = new SqlDataAdapter(cmd))
    {
        cmd.Parameters.AddWithValue("@BoardID", boardId);
        adapter.Fill(dt);
    }
    return dt.DefaultView; // 支援 RowFilter
}

遞迴建立 TreeView 節點


private DataView _folderView;

public void LoadTree(int boardId)
{
    _folderView = GetFolderDataView(boardId);
    treeView1.Nodes.Clear();
    CreateTreeNodes(treeView1.Nodes, 0); // 從根節點 (ParentFolderID=0) 開始
    treeView1.ExpandAll();
}

private void CreateTreeNodes(TreeNodeCollection parentNodes, int parentId)
{
    _folderView.RowFilter = $"ParentFolderID = {parentId}";

    foreach (DataRowView row in _folderView)
    {
        var node = new TreeNode
        {
            Text = row["FolderName"].ToString().Trim(),
            Name = row["FolderID"].ToString(), // 用 Name 存 ID
            Tag = row["FolderID"]            // Tag 也存 ID 方便轉型
        };

        parentNodes.Add(node);

        // 遞迴建立子節點
        CreateTreeNodes(node.Nodes, Convert.ToInt32(row["FolderID"]));
    }
}

效能優化:大量節點分頁/延遲載入

若節點超過數千,一次載入會卡頓。改用「展開時載入」模式:


private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
    if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Text == "Loading...")
    {
        e.Node.Nodes.Clear();
        LoadChildNodes(e.Node);
    }
}

private void LoadChildNodes(TreeNode parentNode)
{
    int parentId = Convert.ToInt32(parentNode.Tag);
    string sql = "SELECT FolderID, FolderName FROM BBS_BestArticleFolder WHERE ParentFolderID = @ParentID";
    using (var conn = new SqlConnection(_connStr))
    using (var cmd = new SqlCommand(sql, conn))
    {
        cmd.Parameters.AddWithValue("@ParentID", parentId);
        conn.Open();
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                var child = new TreeNode
                {
                    Text = reader["FolderName"].ToString(),
                    Name = reader["FolderID"].ToString(),
                    Tag = reader["FolderID"]
                };
                // 加入假節點觸發 BeforeExpand
                child.Nodes.Add("Loading...");
                parentNode.Nodes.Add(child);
            }
        }
    }
}

常見操作

操作代碼片段
取得選中節點 IDint id = Convert.ToInt32(treeView1.SelectedNode.Tag);
新增子節點parentNode.Nodes.Add(new TreeNode("新資料夾") { Tag = newId });
刪除節點treeView1.SelectedNode.Remove();
搜尋節點treeView1.Nodes.Find("key", true); (需設定 Name)
拖曳排序設定 AllowDrop=true,處理 ItemDrag/DragEnter/DragDrop

WPF / WinUI 3 對應

  • WPF:TreeView + HierarchicalDataTemplate + ObservableCollection (MVVM)
  • WinUI 3:TreeView + x:Bind + 增量載入 (ISupportIncrementalLoading)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved