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
}
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);
}
}
}
}
| 操作 | 代碼片段 |
|---|---|
| 取得選中節點 ID | int 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 |
TreeView + HierarchicalDataTemplate + ObservableCollection (MVVM)TreeView + x:Bind + 增量載入 (ISupportIncrementalLoading)