109 lines
3.1 KiB
C#
109 lines
3.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Ewide.Core
|
|
{
|
|
/// <summary>
|
|
/// 树基类
|
|
/// </summary>
|
|
public interface ITreeNode
|
|
{
|
|
/// <summary>
|
|
/// 获取节点id
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
string GetId();
|
|
|
|
/// <summary>
|
|
/// 获取节点父id
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
string GetPid();
|
|
|
|
/// <summary>
|
|
/// 设置Children
|
|
/// </summary>
|
|
/// <param name="children"></param>
|
|
void SetChildren(IList children);
|
|
}
|
|
public class TreeBuildSetting
|
|
{
|
|
public bool AddEmptyChildren { get; set; } = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 递归工具类,用于遍历有父子关系的节点,例如菜单树,字典树等等
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public class TreeBuildUtil<T> where T : ITreeNode
|
|
{
|
|
TreeBuildSetting _setting;
|
|
public TreeBuildUtil(TreeBuildSetting setting = null)
|
|
{
|
|
_setting = setting ?? new TreeBuildSetting();
|
|
}
|
|
/// <summary>
|
|
/// 顶级节点的父节点Id(默认0)
|
|
/// </summary>
|
|
private readonly List<string> _rootParentIds = new List<string> { string.Empty, Guid.Empty.ToString() };
|
|
|
|
/// <summary>
|
|
/// 构造树节点
|
|
/// </summary>
|
|
/// <param name="nodes"></param>
|
|
/// <returns></returns>
|
|
public List<T> DoTreeBuild(List<T> nodes)
|
|
{
|
|
nodes.ForEach(u => BuildChildNodes(nodes, u, new List<T>()));
|
|
|
|
var results = new List<T>();
|
|
nodes.ForEach(u =>
|
|
{
|
|
if (_rootParentIds.Contains(u.GetPid()))
|
|
results.Add(u);
|
|
});
|
|
|
|
// 在未获取到根节点的情况下, 直接将最上级作为根节点
|
|
if (results.Count < 1)
|
|
{
|
|
var ids = new List<string>();
|
|
nodes.ForEach(u =>
|
|
{
|
|
ids.Add(u.GetId());
|
|
});
|
|
|
|
nodes.ForEach(u =>
|
|
{
|
|
if (!ids.Contains(u.GetPid()))
|
|
results.Add(u);
|
|
});
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 构造子节点集合
|
|
/// </summary>
|
|
/// <param name="totalNodes"></param>
|
|
/// <param name="node"></param>
|
|
/// <param name="childNodeLists"></param>
|
|
private void BuildChildNodes(List<T> totalNodes, T node, List<T> childNodeLists)
|
|
{
|
|
var nodeSubLists = new List<T>();
|
|
totalNodes.ForEach(u =>
|
|
{
|
|
if (u.GetPid().Equals(node.GetId()))
|
|
nodeSubLists.Add(u);
|
|
});
|
|
nodeSubLists.ForEach(u => BuildChildNodes(totalNodes, u, new List<T>()));
|
|
childNodeLists.AddRange(nodeSubLists);
|
|
if (childNodeLists.Count > 0 || _setting.AddEmptyChildren)
|
|
{
|
|
node.SetChildren(childNodeLists);
|
|
}
|
|
}
|
|
}
|
|
}
|