C#动态生成一个目录树

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了,而是按照你的递增规律来写。


  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C#中,动态生成枚举类型是一种比较特殊的需求,因为枚举类型在编译时就已经确定了。不过,你可以通过使用反射和动态代码生成来实现这个目标。 首先,你可以使用System.Reflection.Emit命名空间中的类来动态生成一个新的枚举类型。以下是一个简单的示例代码: ```csharp using System; using System.Reflection; using System.Reflection.Emit; public class Program { public static void Main() { // 创建一个动态程序集 AssemblyName assemblyName = new AssemblyName("DynamicEnumAssembly"); AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); // 创建一个动态模块 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicEnumModule"); // 创建一个动态枚举类型 EnumBuilder enumBuilder = moduleBuilder.DefineEnum("DynamicEnumType", TypeAttributes.Public, typeof(int)); // 添加枚举值 enumBuilder.DefineLiteral("Value1", 0); enumBuilder.DefineLiteral("Value2", 1); enumBuilder.DefineLiteral("Value3", 2); // 创建枚举类型 Type dynamicEnumType = enumBuilder.CreateType(); // 使用动态枚举类型 Console.WriteLine($"Dynamic Enum Type: {dynamicEnumType}"); // 输出枚举值 foreach (var value in Enum.GetValues(dynamicEnumType)) { Console.WriteLine(value); } } } ``` 上述代码中,我们使用`AssemblyBuilder`和`ModuleBuilder`来创建一个动态程序集和动态模块。然后,使用`EnumBuilder`来定义一个新的枚举类型,并使用`DefineLiteral`方法添加枚举值。最后,通过调用`CreateType`方法来创建枚举类型。 请注意,动态生成的枚举类型在运行时是完全独立的,与预定义的枚举类型没有任何关联。因此,你需要使用反射来操作和使用这个动态生成的枚举类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值