在編程中很可能使用到多級動態目錄,如果使用一般的方法將多級目錄綁定到Treeview就顯得非常局促了,所以,最好的辦法就是使用遞歸,使用遞歸就完全不用去考慮目錄的層次有多深.
代碼其實很簡單.

1 protected void Page_Load(object sender, EventArgs e) 2 { 3 string connstring = "Data Source=.;Initial Catalog=MyDB;Persist Security Info=True;User ID=sa;Password=******"; 4 SqlConnection con = new SqlConnection(connstring); 5 SqlDataAdapter sda = new SqlDataAdapter( "select ID,ParentID,Name from Sys_Directory where isuse=1",con); 6 DataSet ds = new DataSet(); 7 sda.Fill(ds); 8 DataTable dt = ds.Tables[0]; 9 BindTree(dt,null,0); 10 } 11 private void BindTree(DataTable dt, TreeNode parentnode, int parentid) 12 { 13 14 DataRow[] rows = dt.Select(string.Format("ParentID={0}", parentid)); 15 foreach (DataRow row in rows) 16 { 17 TreeNode node = new TreeNode(); 18 node.Text = row["Name"].ToString(); 19 node.Value = row["ID"].ToString(); 20 BindTree(dt, node,Convert.ToInt32( row["ID"])); 21 if (parentnode == null) 22 { 23 tv1.Nodes.Add(node); 24 } 25 else 26 { 27 parentnode.ChildNodes.Add(node); 28 } 29 } 30 31 }
在遞歸方法中,傳遞一個我們從數據庫中查詢出來的datatable數據源,一個TreeNode,以及目錄的父級ID.
下面這句話可能有些人不理解,dt.Select是系統的方法,按照主鍵順序匹配每一條數據.這里的主鍵並非數據庫中的主鍵,而是后面括弧中的指定的主鍵.
string.Format是格式化字符串
DataRow[] rows = dt.Select(string.Format("ParentID={0}", parentid));
后面的代碼就是開始循環並遞歸了.
遞歸算法有這樣第一特點,就是先循環遍歷的終點,然后從終點開始遞歸計算.
在將目錄綁定到treeview的時候進行一個判斷,判斷此節點是否為根節點.
但是,如果這個時候你在if處打上斷點,然后F11,會發現,我們開始給parentnode復的null值,這時候判斷卻不是為空的,這是為什么呢?難道給Treenode賦null與parentnode=null不一樣?還是遞歸算法不是循環到終點在從終點遞歸?其實不然.
if (parentnode == null)
{
tv1.Nodes.Add(node);
}
else
{
parentnode.ChildNodes.Add(node);
}
我們回過去看if上面的代碼,BindTree(dt, node,Convert.ToInt32( row["ID"]));
在調用自身方法的時候是需要傳遞一個parentnode參數的,而這個node已經在循環的時候已經賦值了,在開始遞歸的時候這個node的值不是開始的null值,而是你目錄的最后一個子節點.
所以,遞歸開始從最后子節點開始的.最終遞歸到根節點.