LuoNing_
LuoNing_
2021-02-22 09:12
采纳率: 100%
浏览 105

菜鸟请教C# 如何动态追加到treeview的对应子节点上

各位大大们好,我是才学一个月的新手,这个问题研究一天了,搞不定,查了好多资料也没搞定. 

数据库是sql server2008版本的, 语言是C#

数据库结构就像图上这样,每个类别最大有四级分支,需要动态的加载到winform上.第一级很好加上去,可是第二级起我不知道如果让0101饮料类找到他的父节点01上,关键是想实现如下这张图的效果,

 

肯请指点下,只要教我会做到二级就可以了.三四级应该是重复的,菜鸟谢谢各位大神了

 

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • flybox0384
    flybox0384 2021-02-22 10:18
    已采纳

    首先,你的表里数据的数据需要建立起连接,你的表缺少一个父节点字段,

    id no name version pid

    pid就是父节点,根节点是0 ,叶节点的父节点是它上级节点的id

    程序里你取出表中数据,然后如下

    try
                {
                    // 加根节点
                    TreeNode Node = new TreeNode()
                    {
                        Tag = -1,
                        ImageIndex = 0,
                        Text = "食品"
                    };
                    foreach (string name in 取数据的方法)
                    {
                        TreeNode CNode = new TreeNode()
                        {
                            ImageIndex = 2,
                            SelectedImageIndex = 3,
                            Tag = no,
                            Text = name
                        };
                        Node.Nodes.Add(CNode);
                    }
                    TreeView.Nodes.Add(Node);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(GlobleHelper.ErrorLog, "处理treeview出错:" + ex, GlobleHelper.WriteLog);
                }

    点赞 评论
  • waterljb
    Water Lee 2021-02-22 09:30

    即是学习,给几个建议吧

    1、树型结构在数据库里必然要存储节点的父节点编号,而不应该是通过计算才能得到,这会大降低代码效率,也会增加编码难度

    2、树型处理不可避免的要用到递归方法

     

    点赞 1 评论
  • LuoNing_
    LuoNing_ 2021-02-23 05:42

    谢谢大家,我的问题已解决,这里分享下学习所得,也方便后面的菜鸟.

    在@Water Lee和@flybox0384的指点下,我把数据库更改为

     

    数据库pid这一列一级分支pid=no,从二级分支开始,pid=no.Substring(0,2-4-6位了),也就是父节点的no;

    下面是代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Data.SqlClient;
    namespace WindowsFormsApp21
    {
        public partial class Form3 : Form
        {
            public Form3()
            {
                InitializeComponent();
            }
            public static readonly string conStr = "Server=PS-12\\SQLEXPRESS;Database=Test_6;Uid=sa;Pwd=0000";
    
            private void Form3_Load(object sender, EventArgs e)
            {
                try
                {
                    TreeNode MarketName = new TreeNode("本店名称");//这个是根节点,这项不允许被删除,为了方便当所有子节点删光后再新增时找不到selectednode
                    MarketName.Tag = 0;//根节点的tag不能和表中将要分配的tag重复,重复了子节点追加到根这一行了
                    treeView1.Nodes.Add(MarketName);
    
                    SqlConnection con = new SqlConnection(conStr);
                    con.Open();
                    string sql = "select * from Class_Root";
                    SqlCommand com = new SqlCommand(sql, con);
                    SqlDataReader dr = com.ExecuteReader();
                    while (dr.Read())
                    {
                        string rootNo1 = dr["no"].ToString();//这三行分别从数据库中读值
                        string name = dr["name"].ToString();
                        string pid = dr["pid"].ToString();
                        string nodeName = rootNo1 + name;//这行可以不要,我只是为了方便引用
                        int length = rootNo1.Length;//我这里是根据编码no的长度判断是哪一级树节点
                        switch (length)//根据no长度不同做出选择
                        {
                            case 2://no长度2就是一级:01食品
                                TreeNode classname1 = new TreeNode(nodeName);
                                classname1.Tag = rootNo1;//一定要给tag值,不然子节点找不到父节点,如果你的节点名字和待找对象一致就可以不给
                                MarketName.Nodes.Add(classname1);
                                break;
    
                            case 4://no长度4就是二级:0101饮料
                                TreeNode classname2 = new TreeNode(nodeName);
    
                                //调用递归FindNode
                                TreeNode tnRet = null;
                                foreach (TreeNode tn in MarketName.Nodes)
                                {
                                    tnRet = FindNode(tn, pid);
                                    if (tnRet != null)
                                    {
                                        classname2.Tag = rootNo1;
                                        tnRet.Nodes.Add(classname2);
                                    }
                                }
                                break;
    
                            case 6://no长度6就是三级:010101碳酸型
                                TreeNode classname3 = new TreeNode(nodeName);
    
                                //调用递归FindNode
                                TreeNode tnRet2 = null;
                                foreach (TreeNode tn in treeView1.Nodes)
                                {
                                    //string FartherNoIsSonPid = rootNo1.Substring(0,4);
                                    tnRet2 = FindNode(tn, pid);
                                    if (tnRet2 != null)
                                    {
                                        classname3.Tag = rootNo1;
                                        tnRet2.Nodes.Add(classname3);
                                    }
                                }
                                break;
    
                            case 8://no长度8就是四级:01010101百事
                                TreeNode classname4 = new TreeNode(nodeName);
    
                                //调用递归FindNode
                                TreeNode tnRet3 = null;
                                foreach (TreeNode tn in treeView1.Nodes)
                                {
                                    //string FartherNoIsSonPid = rootNo1.Substring(0,4);
                                    tnRet3 = FindNode(tn, pid);
                                    if (tnRet3 != null)
                                    {
                                        classname4.Tag = rootNo1;
                                        tnRet3.Nodes.Add(classname4);
                                    }
                                }
                                break;
    
                                //如果还有更多分支可以继续往下分case
                        }
    
                    }
                    dr.Close();
                    con.Close();
                }
                catch (Exception ex)
                {
    
                    MessageBox.Show(ex.Message);//我为了到看错误直接显示错误,实际用了就不要学我了
                }
                treeView1.ExpandAll();//展开所有节点
            }
    
    
    
    
    
    
            //递归查树节点-------这部分是从网上找的,我根据情况改了一下
            private TreeNode FindNode(TreeNode tnParent, string strValue)//atrValue是tag值
            {
                if (tnParent == null) return null;//非空判断
                //if (tnParent.Text == strValue) return tnParent;//如果目标名称和要传递参数一致就用这行
                if (tnParent.Tag.ToString() == strValue)//我这里改成查找节点tag,因为我的节点名称是no+name连接起来的,直接查名称肯定查不到,tag值才是父节点
                    return tnParent;
    
                TreeNode tnRet = null;
                foreach (TreeNode tn in tnParent.Nodes)//循环查找主函数给到的树tnParent中的节点
                {
                    tnRet = FindNode(tn, strValue);//递归到主方法再次取参数
                    if (tnRet != null)
                        break;//如果找到则中断
                }
                return tnRet;//最后返回
            }
        }
    }
    

    最后效果

    分享给和我一样的菜鸟

      点赞 1 评论

    相关推荐