前言:
今天在群里有人问起了我一个比较远古的问题:带线的无限级下拉树列表他运行不起来。
最关键的又扯上了CYQ.Data 框架,让我一时觉得比较悬,因为文章是08年时写的,而框架最今年才发力完善的,
所以两者应该是没啥联系的,不过这一问也好,给了我一个写此文章的机会。
ps:他把示例的其它代码当成是 CYQ.Data 框架 里的代码。
最关键的又扯上了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;
}
}
}
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
}
}
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
}
}
{
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
}
}
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>
<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");
}
{
new Tree.ProductTree().DropDownTree.Bind(ddlProduct,null, "0");
}
4:最后的输出结果,如图
最后提示:
1:提供示例源码下载:--点击下载 [最近很少写文,点击下载的你别忘了点下推荐哦^-^]]
2:秋色园V2.5将在近期发布,欢迎提前浏览 http://www.cyqdata.com
PS:传说点一下推荐会有10个园豆,喜欢麻烦点一下“推荐”,thank you very much!!
版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。 |
个人微信公众号 |
Donation(扫码支持作者):支付宝: |
Donation(扫码支持作者):微信: |