今儿个给大伙来一篇干货,树形结构 构建算法
客户端是用ztree控件实现的,我们先来看下展示效果
直接上model类文件
//部门数据结构类
public class DepartModel
{
public int DepartID { get; set; }
public string DepartName { get; set; }
public string DepaetNo { get; set; }
public int ParDepartID { get; set; }
public string DepartLevel { get; set; } //层级树,存储所有父节点id,以逗号隔开的方式
public string DepartCode { get; set; }
public string TreeText { get; set; }
public int? Rank { get; set; }
}
//组建树形数据结构
public class TreeNodeDepart
{
public int id { get; set; }
public int pid { get; set; }
public string text { get; set; }
public string departCode { get; set; }
public string departLevel { get; set; }
public List<TreeNodeDepart> children { get; set; }
}
再上递归算法
public class DepartUserController : BaseController
{
public ActionResult GetPageTree()
{
List<DepartModel> list = base.GetDepartList();//获取所有数据,,结构如model所示
var selectModel = list.OrderBy(p => p.ParDepartID).FirstOrDefault(); //按照父节点排序,找到最大的父节点ID
int parendId = 0;
if (selectModel != null)
{
parendId = selectModel.ParDepartID;//根节点ID
}
var newList = ToTreeNodes(list, parendId);
return Json(newList);
}
public List<TreeNodeDepart> ToTreeNodes(IList<DepartModel> listPer, int parent)
{
List<TreeNodeDepart> listNodes = new List<TreeNodeDepart>();
LoadTreeNode(listPer, listNodes, parent);//生成树节点时,根据pid=0的根节点来生成
return listNodes;
}
public void LoadTreeNode(IList<DepartModel> listPer, List<TreeNodeDepart> listNodes, int pid)
{
var childNode = listPer.Where(s => s.ParDepartID == pid);//根据父节点pid过滤所有子节点数据
if (childNode.Any())//判断是否有子节点数据
{
foreach (var item in childNode)
{
TreeNodeDepart node = ToNode(item);//将父节点为pid的子节点构建为新的节点
listNodes.Add(node);//将节点加入到树节点集合
LoadTreeNode(listPer, node.children, node.id); //递归 为这个新创建的树节点找子节点
}
}
}
public TreeNodeDepart ToNode(DepartModel objDepart)
{
TreeNodeDepart node = new TreeNodeDepart()
{
id = objDepart.DepartID,
pid = objDepart.ParDepartID,
text = objDepart.DepartName,
departCode = objDepart.DepartCode,
departLevel = objDepart.DepartLevel,
children = new List<TreeNodeDepart>()
};
return node;
}
}
另一种实现方案,基于多级文件菜单的:
其实无非也就是循环遍历将扁平化数据构建成树形数据
下面的方案比较简单,But,从效率上来讲可能没有上面那种方案好
代码如下:
public class HelpCenterController
{
BHelpCenter bllHelpCenter = BHelpCenter.GetInstance();
public IHttpActionResult GetList(string groupNo ="0")
{
ApiResultMsg apiResult = new ApiResultMsg { Code = 0 };
var list = bllHelpCenter.GetAllByCondition(new SEHelpCenter() {GroupNo= groupNo });
List<EHelpCenter> array = new List<EHelpCenter>();
foreach (var item in list)
{
if (item.ParentID == 0)
{
array.Add(item);
}
}
apiResult.Data = children(array, list);
return Json(apiResult);
}
public List<EHelpCenter> children(List<EHelpCenter> parent, IList<EHelpCenter> list)
{
if (parent != null)
{
foreach (var item in parent)
{
item.childrenList = new List<EHelpCenter>();
foreach (var dataItem in list)
{
if (dataItem.ParentID == item.HelpCenterID)
{
item.childrenList.Add(dataItem);
}
}
children(item.childrenList, list);
}
}
return parent;
}
}
//实体类文件,为了方便就不单独聆出来了
public partial class EHelpCenter
{
public virtual int? HelpCenterID { get; set; }
public virtual int? ParentID { get; set; }
public virtual string Title { get; set; }
public virtual string Des { get; set; }
public virtual int? Rank { get; set; }
public virtual string AddUserName { get; set; }
public virtual DateTime? AddTime { get; set; }
public virtual string GroupNo { get; set; }
public List<EHelpCenter> childrenList{ get; set; }
}
接口请求 获取到的数据结构如图所示:
想了下,还是把相关的js代码附上
html 部分 在头部或者尾部引入zTree 相关js包,使用ul控件来存放树形数据
注意要点:在引入zTree.js相关包之前必须先引用jQuery包
<div data-options="region:'west',title:'组织管理'" style="width:230px;">
<ul id="tree" class="ztree"></ul>
</div>
@section scripts{
<script src="~/Scripts/ztree-v3/jquery.ztree.core.min.js"></script>
<script src="~/Scripts/ztree-v3/jquery.ztree.excheck.min.js"></script>
<script src="~/Scripts/ztree-v3/jquery.ztree.exedit.min.js"></script>
<script src="~/Areas/Admin/Scripts/DepartUser/Index.js"></script>
}
js部分代码
var zTreeObj,
setting = {
view: {
selectedMulti: false
},
data: {
key: { //节点显示属性配置
name: "text",
}
},
edit: {
enable: true,//开启节点拖拽控制
showRemoveBtn: false //删除按钮控制
},
callback: {//各类回调函数
onClick: zTreeOnClick,
beforeDrop: zTreeBeforeDrop,
onDrop: zTreeOnDrop,
beforeRename: zTreeBeforeRename,
onRename: zTreeOnRename
}
},
zTreeNodes = [{//初始化数据
"name": "网站导航", open: true, children: [
{ "name": "google", "url": "http://g.cn", "target": "_blank" },
{ "name": "baidu", "url": "http://baidu.com", "target": "_blank" },
{ "name": "sina", "url": "http://www.sina.com.cn", "target": "_blank" }
]
}];
window.onload = function(){
InitTree();
}
function InitTree() {
$.ajax({
url: "/Admin/DepartUser/GetPageTree",
data: {},
type: 'post',
async: false,
success: function (data) {
zTreeNodes = data;
},
})
zTreeObj = $.fn.zTree.init($("#tree"), setting, zTreeNodes);
zTreeObj.expandAll(true);//展开所有节点
}
当然,数据也可以不在服务端处理,统一返回数组对象到js客户端做处理,代码也比较简洁,这里可以参考一下这位朋友的js代码