在编程中很可能使用到多级动态目录,如果使用一般的方法将多级目录绑定到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值,而是你目录的最后一个子节点.
所以,递归开始从最后子节点开始的.最终递归到根节点.