無限分類是許多系統中常見的需求,例如商品分類、文章分類、組織架構等。其核心資料結構極為簡單,僅需「分類編號」與「上級編號」兩個欄位即可構建無限層級的樹狀結構。為了方便查詢,實務上常額外增加「深度」欄位,但本文範例僅採用雙欄位設計,透過遞歸方式將資料綁定至 TreeView 與 DropDownList 控制項,展示兩種最經典的實作方式。
TreeView 是 ASP.NET 內建的階層式資料展示控制項,非常適合呈現樹狀結構。以下程式碼示範如何在 Page_Load 事件中啟動遞歸綁定:
public partial class _Default : System.Web.UI.Page
{
BIL bil = new BIL();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bind_tree("0", null); // 從根節點(ParentId = "0")開始遞歸
}
}
protected void bind_tree(string parentId, TreeNode parentNode)
{
DataTable dt = bil.GetByClassPre(parentId).Tables[0];
foreach (DataRow dr in dt.Rows)
{
TreeNode node = new TreeNode();
node.Text = dr["ClassName"].ToString();
if (parentNode == null)
{
// 根節點直接加入 TreeView
this.TreeView1.Nodes.Add(node);
bind_tree(dr["ClassId"].ToString(), node);
}
else
{
// 子節點加入父節點的 ChildNodes 集合
parentNode.ChildNodes.Add(node);
bind_tree(dr["ClassId"].ToString(), node);
}
}
}
}
關鍵點解析:
bil.GetByClassPre(parentId):資料存取層方法,根據上級編號查詢子分類。foreach 迴圈不執行,自然返回上一層。TreeNode 物件在每次迴圈中新建,確保節點獨立。DropDownList 扁平化呈現,需透過字串前綴(如空格或「|-」)模擬層級感。以下方法採用 tmp 參數累加縮排字元:
protected void bind_droplist(string parentId, string indent)
{
DataTable dt = bil.GetByClassPre(parentId).Tables[0];
foreach (DataRow dr in dt.Rows)
{
if (dr["ClassPre"].ToString() == "0")
{
// 根節點:無縮排
indent = "";
DropDownList1.Items.Add(dr["ClassName"].ToString());
bind_droplist(dr["ClassId"].ToString(), indent + " ");
}
else
{
// 子節點:加上縮排與前綴
DropDownList1.Items.Add(indent + "|-" + dr["ClassName"].ToString());
bind_droplist(dr["ClassId"].ToString(), indent + " ");
}
}
}
補充說明:
若資料量極大,遞歸可能導致效能問題或堆疊溢位。實務上可考慮:
Depth(深度)與 Path(路徑,如 "001.003.012")欄位,一次性查詢後在記憶體中排序組裝。本文展示了無限分類最基礎的兩種前端綁定實作。TreeView 適合後台管理樹狀操作;DropDownList 適合前台下拉選單選擇。核心邏輯皆為「查詢子節點 → 建立節點 → 遞歸處理子節點」,理解此模式即可輕鬆擴展至其他場景(如組織架構樹、多級選單等)。