带线的无限级下拉树列表-完整示例篇

前言:

今天在群里有人问起了我一个比较远古的问题:带线的无限级下拉树列表他运行不起来。

最关键的又扯上了CYQ.Data 框架,让我一时觉得比较悬,因为文章是08年时写的,而框架最今年才发力完善的,

所以两者应该是没啥联系的,不过这一问也好,给了我一个写此文章的机会。

ps:他把示例的其它代码当成是 CYQ.Data 框架 里的代码。

 

 

本文将对之前的代码进行小小的简化,并为之建立一个完整的应用示例,以下为正式应用步骤:

 

一:新建项目

1:将IDropDownTree及DropDownTree放到类里,如下图:

简化后的代码如下:

IDropDownTree

IDropDownTree
using  System.Collections.Generic;
using System;
namespace  Tree
{
    
public   interface  IDropDownTree : IDisposable
    {
        
///   <summary>
        
///  返回Dictionary里分别对应ID,文本,如果没有子节点返回null
        
///   </summary>
        
///   <param name="parentID"> 父节点ID </param>
        
///   <returns></returns>
        Dictionary < string string >  GetChildList( string  parentID);

        
///   <summary>
        
///  实现的代码里写return new Tree.DropDownTree(this);
        
///   </summary>
        DropDownTree DropDownTree
        {
            
get ;
        }
    }
}

 

DropDownTree

DropDownTree
using  System.Collections.Generic;
using  System.Web.UI.WebControls;
namespace  Tree
{
    
public   sealed   class  DropDownTree
    {
        IDropDownTree _DropDownTree;
        
public  DropDownTree(IDropDownTree dropDownTree)
        {
            _DropDownTree 
=  dropDownTree;
        }
        
///   <summary>
        
///  用于树的前缀
        
///   </summary>
        
///   <param name="IsLast"> 是否是同级节点中的最后一个 </param>
        
///   <param name="HasChild"> 本节点是否拥有子节点 </param>
        
///   <param name="ParentString"> 父节点前缀符号 </param>
        
///   <returns> 本节点的前缀 </returns>
         private   string  GetPreFix( bool  isLast,  bool  hasChild,  string  parentString)
        {
            
string  result  =   string .Empty;
            
if  ( ! string .IsNullOrEmpty(parentString))
            {
                parentString 
=  parentString.Remove(parentString.Length  -   1 ).Replace( " " " " ).Replace( " " "   " );
                result 
+=  parentString;
            }
            result 
+=  isLast  ?   " "  :  " " ;
            result 
+=  hasChild  ?   " "  :  " " ;
            
return  result;
        }
        
#region  绑定下拉菜单

        
///   <summary>
        
///  绑定连动级的下拉菜单
        
///   </summary>
        
///   <param name="ddlGoodsType"> 传进一个被绑定的DropDownList </param>
        
///   <param name="removeID"> 被排除绑定的节点ID </param>
         public   void  Bind(ListControl dropDown,  string  removeID,  string  parentID)
        {
            
            ListItem listItem 
=   null ;
            
string  currentID  =  parentID; // 根节点/父ID
             string  currentSign  =   string .Empty; // 当前节点符号;
             string  parrentSign  =   string .Empty;  // 父节点符号;
             bool  HasChild  =   true ; // 是否有子
            Queue < string >  parentKeyList  =   new  Queue < string > (); // 存 有子节点的 节点ID
            Queue < string >  parentSignList  =   new  Queue < string > (); // 对应节点ID的前缀符号
             int  itemIndexOf  =   0 ; // 父节点所在的位置 
             while  (HasChild)
            {
                
int  lastOneCount  =   1 ; // 用于计算在同级别中是否最后一个
                Dictionary < string string >  childList  =  _DropDownTree.GetChildList(currentID); //  得到子节点列表
                 if  (childList  !=   null )
                {
                    
if  ( ! string .IsNullOrEmpty(removeID)  &&  childList.ContainsKey(removeID))
                    {
                        childList.Remove(removeID);
                    }
                    
foreach  (KeyValuePair < string string >  entry  in  childList)
                    {
                        
if  (_DropDownTree.GetChildList(entry.Key)  !=   null ) // 存在子
                        {
                            currentSign 
=  GetPreFix(lastOneCount  ==  childList.Count,  true , parrentSign);
                            listItem 
=   new  ListItem(currentSign  +  entry.Value, entry.Key);

                            parentKeyList.Enqueue(entry.Key);
// 当前的节点ID
                            parentSignList.Enqueue(currentSign); // 当前的节点符号
                        }
                        
else // 不存在子
                        {
                            currentSign 
=  GetPreFix(lastOneCount  ==  childList.Count,  false , parrentSign);
                            listItem 
=   new  ListItem(currentSign  +  entry.Value, entry.Key);
                        }
                        
if  (dropDown.Items.Count  !=   0 )
                        {
                            itemIndexOf 
=   string .IsNullOrEmpty(currentID)  ?  itemIndexOf  +   1  : dropDown.Items.IndexOf(dropDown.Items.FindByValue(currentID))  +  lastOneCount;
                        }
                        dropDown.Items.Insert(itemIndexOf, listItem);
// 添加子节点
                        lastOneCount ++ ;
                    }
                    
if  (parentKeyList.Count  >   0 ) // 存在子节点时
                    {
                        currentID 
=  parentKeyList.Dequeue();
                        parrentSign 
=  parentSignList.Dequeue();
                    }
                    
else
                    {
                        HasChild 
=   false ;
                    }
                }
                
else
                {
                    
break ;
                }

            }
            _DropDownTree.Dispose();
        }
        
#endregion
    }
}

 

二:数据库数据准备

1:为方便示例,这里用了Access数据库,新建一个Product表,并为之添加了几行数据,如图:

 

三:引用CYQ.Data框架来实现

1:项目添加CYQ.Data引用

2:新建ProductTree类,实现IDropDownTree接口

A:为表增加枚举,如下:

namespace  Entity
{
    
public   enum  TableNames
    {
        Product
    }
    
public   enum  Product
    {
        ID,
        ParentID,
        Name
    }
}

 

B:实现接口

using  Tree;
using  CYQ.Data;
using  Entity;
using  CYQ.Data.Table;
using  System.Collections.Generic;

namespace  Tree
{
    
///   <summary>
    
///  作者:路过秋天
    
///  博客: http://cyq1162.cnblogs.com
    
///  秋色园: http://www.cyqdata.com
    
///   </summary>
     public   class  ProductTree : IDropDownTree
    {
        
int  count  =   0 ;
        
private  MAction action;
        
public  ProductTree()
        {
            action 
=   new  MAction(TableNames.Product);
        }

        
#region  IDropDownTree 成员

        
public  Dictionary < string string >  GetChildList( string  parentID)
        {

            MDataTable table 
=  action.Select( 0 0 " ParentID= "   +  parentID,  out  count);
            Dictionary
< string string >  dic  =   null ;
            
if  (count  >   0 )
            {
                dic 
=   new  Dictionary < string string > ();
                
foreach  (MDataRow row  in  table.Rows)
                {
                    dic.Add(row.Get
< string > (Product.ID), row.Get < string > (Product.Name));
                }
            }
            
return  dic;
        }

        
public  DropDownTree DropDownTree
        {
            
get
            {
                
return   new  DropDownTree( this );
            }
        }

        
#endregion

        
#region  IDisposable 成员

        
public   void  Dispose()
        {
            action.Close();
        }

        
#endregion
    }
}

项目解决方案如下图:

 

四:展示应用结果

1:新建测试站点WebDemo项目,并将数据库放到App_Data目录下,如图:

2:Web.config配置好数据库链接如下:

< appSettings >
    
< add  key ="AccessDbNameForWeb"  value ="App_Data/tree.mdb" />
</ appSettings >
< connectionStrings >
    
< add  name ="Conn"  connectionString ="Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}"  providerName ="System.Data.OleDb" />
</ connectionStrings >

 

3:Default.界面调用代码

前台:

放一下拉框: < asp:DropDownList  ID ="ddlProduct"  runat ="server" ></ asp:DropDownList >

 

后台:

  protected   void  Page_Load( object  sender, EventArgs e)
 {
     
new  Tree.ProductTree().DropDownTree.Bind(ddlProduct, null " 0 " );
 }

 

4:最后的输出结果,如图

 

最后提示:

1:提供示例源码下载:--点击下载 [最近很少写文,点击下载的你别忘了点下推荐哦^-^]]

2:秋色园V2.5将在近期发布,欢迎提前浏览 http://www.cyqdata.com

 

 

PS:传说点一下推荐会有10个园豆,喜欢麻烦点一下“推荐”,thank you very much!!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值