描述:数据库里有四个字段ID (标识,主键),  startAddress(起始地),  endAddress(终止地),  Name (线路名称,手动命名)构建一个树 |--起始地1
 |   |
 |   |_____目的地1
 |    |        |____线路名称1
 |    |        |____线路名称2
 |    |   
 |    |_____目的地2
 |             |____线路名称1
 |             |____线路名称2
 |
 |--起始地2
    |
    |_____目的地1
    |        |___线路名称1
    |        |___线路名称2
    |
    |_____目的地2
             |___线路名称1
             |___线路名称2【求助】:公司项目要构建这样的一棵树(.net c#),请教高手多给指点,在线等,急!

解决方案 »

  1.   

    ID (标识,主键),  startAddress(起始地),  endAddress(终止地),  Name (线路名称,手动命名) 
    加个 parentIDID (标识,主键), parentID(父ID), startAddress(起始地),  endAddress(终止地),  Name (线路名称,手动命名) 
      

  2.   

    我觉得你这个数据库设计不够灵活
    我是这样设计的,,
    在数据库里先保存一行菜单:
    编号id  模块名lable  父节点编号parentId   信息arg     (这一行是字段名)
    1      根节点       0                  {地址1,地址2,地址3}
    2      地址1        1                  null
    3      地址2        1                  null
    4      地址1-1      2                  null
    5      地址1-2      2                  null
    6      地址1-3      2                  null
    7      地址2-1      3                  null
    8      地址2-2      3                  null
    9      地址2-3      3                  null先贴下代码首先用sql语句查询根节点:sqlText = "select 信息 form table where 模块名 = 根节点";
    把结果保存到一个字符串中去:param
    接下来调方法InitTree(param);根据根节点所包含的二级节点名查找子节点
                     void InitTree(string param)
    {
    //根据节点菜单字符串建立数组
    string[] nodeNames=param.Split(',');
    TreeNode tn=null;
    //遍及数组建立树节点
    foreach(string name in nodeNames)
    {
    //添加一个节点
    tn=tvAlarm.Nodes.Add(name);
    //从数据库读取菜单子节点信息
    DataTable tbSubMenus=GetSubMenusByName(name);
    if(tbSubMenus!=null)
    {
    TreeNode subNode=null;
    //遍历子菜单列表
    foreach(DataRow row in tbSubMenus.Rows)
    {
    //添加一个子节点
    subNode = tn.Nodes.Add(row["label"].ToString());
    //subNode.Tag=row["id"].ToString()+","+row["args"].ToString();
    subNode.Tag=row["args"].ToString();
    }
    subNode=null;
    tbSubMenus.Dispose();
    tbSubMenus=null;
    }
    }
    //展开所有节点
    tvAlarm.ExpandAll();
    tn=null;
    } /// 根据菜单名称从数据库获取其子菜单列表
    DataTable GetSubMenusByName(string menuName)
    {
    string commandText=@"
    select [id],label,args from L01_MenuItem 
    where ParentId=(
    select [id] from L01_MenuItem
    where label='"+menuName+@"') ";
    DataTable result=
    Strongsoft.SLDESS.DatabaseEx.DBManager.SystemDatabaseExec.ExecDataTable(commandText);
    if(result!=null && result.Rows.Count==0)
    {
    result=null;
    }
    commandText=null;
    return result;
    }
      

  3.   


    ∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞力争成为中国最大的架构师群联盟,架构师技术交流群:28995710正式开放!!!已经上传的顶级软件产品的架构分析,本群资料仅供研究学习,不得商用!!!
    google 、
    eBay、
    Youtube、
    淘宝等
    ......
    技术文章包括:
    《自己动手写操作系统》
    《搜索引擎-原理、技术与系统》
    《企业应用架构模式》
    ......
    重要的RUP实例
    设计模式精解
    ......
    资料陆续上传中
    ∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞∽∝∞
      

  4.   


    你可以用一个专门保存这些菜单的表来保存
    编号id    模块名lable    父节点编号parentId     信息arg(这一行是字段名) 
    1         根节点            0                  {地址1,地址2,地址3} 
    2         地址1           1                  null 
    3         地址2           1                  null 
    4         地址1-1         2                  null 
    5         地址1-2         2                  null 
    6         地址1-3         2                  null 
    7         地址2-1         3                  null 
    8         地址2-2         3                  null 
    9         地址2-3         3                  null 实际工作中经常还要给数据库增加两个字段一个是IsVisible(是否显示),indexID(排序)
      

  5.   

    第一、从数据库中按“起始地”排序查询出包含所有起始地的无重复数据,然后把这些起始地加入到TreeView控件中(如果需要可以把id加到节点的Tag属性中,以便于按用户所选查询详细信息)。
    第二、从数据库中查询出所有数据,根据第一步中加入到TreeView中的根节点分别向其加入子节点并可把id加入到Tag属性。至此,你要求的树状图已经完成。
    注意,在第一步中还可以使用DbReader只读取id和起始地的信息。
      

  6.   

    ID (标识,主键),cacasd(层级{1,2,3},或者枚举{起始,目的,线路}), parentID(父ID), Name (线路名称,手动命名) 
      

  7.   

    首先很感谢 beblue
    按你的思路我以前也做过,可以实现,不过我想问的是就是按我描述的那数据库的四个字段,是否能实现这样的功能? 
      

  8.   

    哈哈,不好意思,你还需要在第二步中根据根节点向其增加目的节点,方法可以使用DataView.RowFilter来过滤。然后同上向TreeView中加入线路。
      

  9.   

    WPengCH 谢谢你的提示,不过能否麻烦您给个详细的添加或过滤的方法,treeview的属性及事件用不是很熟悉~谢谢!
      

  10.   

    第一、向TreeView中增加根节点:
    string sqlContent = "Select distinct id, 起始地 From Table";
    SqlConnection conn = new SqlConnection("连接字符串");
    SqlCommand cmd = new SqlCommand(sqlContent, conn);
    SqlDataReader reader;
    try
    {
    conn.Open();
    reader = cmd.ExecuteReader();
    while (reader.Read())
    {
    TreeNode node = new TreeNode(reader.GetString(1));
    node.Tag = reader.GetValue(0);
    treeView1.Nodes.Add(node);
    }}
    finally
    {
    if (conn.State != ConnectionState.Closed)
    {
    conn.Close();
    }
    }
      

  11.   

    第二步中根据根节点向其增加目的节点,方法可以使用DataView.RowFilter来过滤 ;过滤是怎样实现的,麻烦麻烦!
      

  12.   

    第二、根据用户单击的根节点动态的加载此节点下的子节点:
    在treeView的AfterSelect事件上加入:
    string sqlContent = string.Format("Select id, 终止地 From Table where 起始地 = '{0}'", e.Node.Text.Trim());
    SqlConnection conn = new SqlConnection("连接字符串");
    SqlCommand cmd = new SqlCommand(sqlContent, conn);
    SqlDataReader reader;
    try
    {
    conn.Open();
    reader = cmd.ExecuteReader();
    e.Node.Nodes.Clear();
    while (reader.Read())
    {
    TreeNode node = new TreeNode(reader.GetString(1));
    node.Tag = reader.GetValue(0);
    e.Node.Nodes.Add(node);
    }
    }
    finally
    {
    if(conn.State != ConnectionState.Closed)
    {
    conn.Close();
    }
    }
    第三、与第二步类似,需要根据用户所选择的起始节和目的地来查询所需数据。在此不就详加说明。
      

  13.   

    很感谢各位的帮忙!更麻烦WPengCH啦!我先测试下,有什么不明白的,我再请教各位!
      

  14.   

    treeview中好像没有AfterSelect事件。。
      

  15.   

    你双击TreeView控件就可以定义AfterSelect事件处理方法了。
      

  16.   

    问题已解决,其实开始想的太复杂,可以用三层循环添加数据到treeview中
    感觉各位的指教具体实现代码如下:using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    public partial class Default3 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            tree(TreeView1);
        }
        public void tree(TreeView treeview1)
        {
            DataSet ds = SqlHelper.ExecuteDataSet(connectionDB.connstring, "tabel", CommandType.Text, "select DISTINCT startAddress from TrafficAddress ", null);
            for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                TreeNode item = new TreeNode();
                item.Text = ds.Tables[0].Rows[i]["startAddress"].ToString();
                item.SelectAction = TreeNodeSelectAction.Expand;            treeview1.Nodes.Add(item);
                DataSet ds2 = SqlHelper.ExecuteDataSet(connectionDB.connstring, "tabel", CommandType.Text, "select DISTINCT endAddress from TrafficAddress where startAddress='" + item.Text + "'", null);
                for (int j = 0; j < ds2.Tables[0].Rows.Count; j++)
                {
                    TreeNode Childitem = new TreeNode();
                    Childitem.Text = ds2.Tables[0].Rows[j]["endAddress"].ToString();
                    Childitem.SelectAction = TreeNodeSelectAction.Expand;                item.ChildNodes.Add(Childitem);                DataSet ds3 = SqlHelper.ExecuteDataSet(connectionDB.connstring, "tabel", CommandType.Text, "select  Name from TrafficAddress where startAddress='" + item.Text + "' and endAddress='" + Childitem.Text + "'", null);
                    for (int k = 0; k < ds3.Tables[0].Rows.Count; k++)
                    {
                        TreeNode Childitem2 = new TreeNode();
                        Childitem2.Text = ds3.Tables[0].Rows[k]["Name"].ToString();
                        Childitem2.SelectAction = TreeNodeSelectAction.Expand;
                        Childitem.ChildNodes.Add(Childitem2);
                    }
                }
            }
        }
    }
      

  17.   

    看了楼主的代码,,是不是可以缩减一下,,写成一个递归的方法if(item.Nodes.Count>1)就递归呵,一个建议而已
      

  18.   

    用SQL语句实现
    第一层 select id,distinct(startAddress) from TableName
    第二层 select id,distinct(endAddress) from TableName where startAddress = (select top 1 startAddress from TableName where id=parentid ) parentid 指上一句的ID
    第三层 select id,Name from TableName where endAddress = (select top 1 endAddress from TableName where id=parentid ) parentid 指上一句的ID
    这样就可以找出树型结构所需的数据,前面有人写的很祥细,我就不写了