1.在生成一个目录树时,如果节点不多,我们可以采用硬编码的方式添加节点,比如这样:
TreeNode tn1 = treeView1.Nodes.Add("一级部门1");
TreeNode tn2 = treeView1.Nodes.Add("一级部门2");
TreeNode tn3 = treeView1.Nodes.Add("一级部门3");
TreeNode tn11 = new TreeNode("二级部门11");
TreeNode tn21 = new TreeNode("二级部门21");
TreeNode tn31 = new TreeNode("二级部门31");
tn1.Nodes.Add(tn11);
tn2.Nodes.Add(tn21);
tn3.Nodes.Add(tn31);
TreeNode tn111 = new TreeNode("三级部门111");
TreeNode tn211 = new TreeNode("三级部门211");
TreeNode tn311 = new TreeNode("三级部门311");
tn11.Nodes.Add(tn111);
tn21.Nodes.Add(tn211);
tn31.Nodes.Add(tn311);
想要实现的效果:
2.但是如果节点增多的话,这样的方式就会显的累赘,而且相当冗长,那么我们可以采用递归的方式来遍历目录树:
首先,在数据库中的表的结构是这样子的:
表中的branch_path字段是目录树中节点值的路径字段,像这样:一级部门1/二级部门11/三级部门111,这在添加节点时非常有用;
branch_tree字段是为每一层节点设置的一个字段,比如说第一层的根节点为1,其余的依次递增;
以上两个字段其实完全没有必要!!这是我在探索动态添加目录树时经历的曲折艰辛道路而设置的字段,
请注意:从 3 到 4 这两步是我用循环遍历的方式添加目录树,但是是一个失败品,它只能添加一层,所以如果你想知道正确的方式,请参阅第5步,但是在3 到4 这两步中也有一些编程小知识点,也有可取之处
3.这样,在动态生成目录树时的代码就是:
try
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
for (int i=1;i<4;i++)
{
cmd.CommandText = "SELECT " +
"branch_code,branch_name,branch_hasSon,branch_parentCode,branch_path FROM tb_branch where branch_tree="+i;//i参数是数据库中部门表中为了界定树的层级而设置的
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = cmd;
DataTable dt = new DataTable();
sda.Fill(dt);//将查询的数据装如DataTable中
//遍历DataTable
if (i==1)
{
TreeNode tnRoot = null;
foreach (DataRow dr in dt.Rows)
{
tnRoot = treeView1.Nodes.Add(dr[1].ToString().Trim());
}
}
else
{
foreach (DataRow dr in dt.Rows)//遍历非根节点
{
string branchPath = dr[4].ToString().Trim();
string[] arr = branchPath.Split(new char[] { '/' });
if (arr.Length == 3)
//遍历非根节点的最后一层节点,因为遍历中间的节点没有意义,而且我至今未找到知道一个节点Text的值,如何
//得到该节点,所以我在数据库中设立了branch_path字段,通过截取字符串,在最后一层添加整个目录树的非根节点
{
foreach (TreeNode tnRoot in treeView1.Nodes)
{
TreeNode tn1 = new TreeNode(arr[1]);
if(tnRoot.Text==arr[0])
{
tnRoot.Nodes.Add(tn1);
TreeNode tn2 = new TreeNode(arr[2]);
tn1.Nodes.Add(arr[2]);
}
}
}
}
}
}
}
catch(Exception ex)
{
}
finally
{
conn.Close();
}
4.至此,我们就动态生成了一个目录树,效果如下:
这样的目录树并不是通过treeView的事件生成的,而是在加载窗体时就形成了。
5.递归生成目录树!!(这才是正确的方法)
首先,数据库中的表的和上面的相同;可以去掉branch_path,branch_tree,branch_hasSon
必须要有的字段:branch_id,branch_code,branch_name,branch_parentCode.
其次,在代码中这样写(我将这部分代码写道了一个初始化方法中):
OtherInit3是添加目录树的方法
public Form1()
{
LinkToDB();
InitializeComponent();
//OtherInit();//其他初始化事件
//OtherInit2();
OtherInit3();
}
DataTable dt0;//声明一个全局的DataTable
private void OtherInit3()
{
try
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from tb_branch";
cmd.Connection = conn;
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = cmd;
dt0= new DataTable();
sda.Fill(dt0);
conn.Close();
//TreeView tv;//树控件
//获得第一级数据,即根目录
DataRow[] drRoot = dt0.Select("len(branch_code)=1");
foreach (DataRow dr in drRoot)
{
TreeNode tn = new TreeNode();
tn.Text = dr["branch_name"].ToString();
treeView1.Nodes.Add(tn);
AppendChild(tn, dr["branch_code"].ToString());
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
}
private void AppendChild(TreeNode tnParent, string branch_code) //递归添加节点
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select branch_code from tb_branch where branch_name='"+tnParent.Text+"'";
cmd.Connection = conn;
string branchCode=(string)cmd.ExecuteScalar();//branchCode是父节点的code
conn.Close();
DataRow[] drs = dt0.Select("(branch_parentCode)="+branchCode+" and len(branch_code)= "+(branch_code.Length+1));//DataTable有Select方法来筛选DataRow,你可以在网上查到这些方法进行了解,此处不再赘述
//int a = drs[0]["branch_code"].ToString().Length;
if(drs!=null)
{
foreach (DataRow dr in drs)
{
TreeNode tn = new TreeNode();
tn.Text = dr["branch_name"].ToString();
tnParent.Nodes.Add(tn);
AppendChild(tn, dr["branch_code"].ToString());
}
}
}
至此,就可以在数据库中添加任意多条数据,前台动态生成这些节点。
注意:branch_code.Length的长度递增取决于你的部门的编号,我的是1,2,3,11,21,31,像这样
如果你是001,001001001,002,002001,那么你的递增书就不是1了,而是按照你的递增规律来写。