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

2年前 (2022) 程序员胖胖胖虎阿
219 0 0

前言:

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

最关键的又扯上了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<stringstring> 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<stringstring> childList = _DropDownTree.GetChildList(currentID);// 得到子节点列表
                if (childList != null)
                {
                    
if (!string.IsNullOrEmpty(removeID) && childList.ContainsKey(removeID))
                    {
                        childList.Remove(removeID);
                    }
                    
foreach (KeyValuePair<stringstring> 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<stringstring> GetChildList(string parentID)
        {

            MDataTable table = action.Select(00"ParentID=" + parentID, out count);
            Dictionary
<stringstring> dic = null;
            
if (count > 0)
            {
                dic 
= new Dictionary<stringstring>();
                
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!!

 

版权声明:程序员胖胖胖虎阿 发表于 2022年11月8日 上午7:40。
转载请注明:带线的无限级下拉树列表-完整示例篇 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...