做项目过程中,经常会遇到树形结构的表,那怎么把这些entity建立树形结构呢?
本文讲述的是存在父子结构的entity建立树结构,最后在TreeView中呈现.
例如现在有一个地区表,
Id name parentId
1 福建 0
2 福州 1
3 厦门 1
4 鼓楼 2
5 湖南 0
6 长沙 5
7 上海 0
8 北京 0
要呈现的结构为:
福建
--福州
----鼓楼
--厦门
湖南
--长沙
上海
北京
像这种父子表的结构我们很多时候都要用了.
1. 抽象出一个ITreeNode接口,
Code
public interface ITreeNode
{
string Id{get;}
string ParentId { get;}
ArrayList Children { get;}
}
public interface ITreeNode
{
string Id{get;}
string ParentId { get;}
ArrayList Children { get;}
}
2.在ITreeNode接口的,实现树结构的生成.
Code
public class Tree
{
private Hashtable _hs;
public Tree(Hashtable hs)
{
if (hs == null)
throw new Exception("the hashtabe is null in Create tree");
_hs = hs;
}
public ArrayList CreateTree()
{
Hashtable parenths = new Hashtable();//保存顶级父亲节点
Hashtable allNodes = new Hashtable();//保存已经添加到树结构的节点
foreach (DictionaryEntry entry in _hs)
{
if (allNodes.Contains(entry.Key))
continue;
if (entry.Value is ITreeNode)
InitTreeNode((ITreeNode)entry.Value, parenths, allNodes);
}
ArrayList roots = new ArrayList();
//将顶级节点添加到roots中
foreach (DictionaryEntry entry in parenths)
{
roots.Add(entry.Value);
}
return roots;
}
/**//// <summary>
/// 反向递归建立树结构
/// </summary>
/// <param name="treeNode">树节点</param>
/// <param name="parenths">保存顶级节点的hashtable</param>
/// <param name="allHs">已经建立节点的hashtable</param>
private void InitTreeNode(ITreeNode treeNode, Hashtable parenths, Hashtable allHs)
{
ITreeNode parentTreeNode;
//如果treenode已经添加,则返回不做任何操作
if (allHs.Contains(treeNode.Id))
return;
if (treeNode.ParentId == "0" || !_hs.Contains(treeNode.ParentId))
{
//如果treenode不存在父节点,则被认为顶级节点
if (!parenths.Contains(treeNode.Id))
parenths.Add(treeNode.Id, treeNode);
if (!allHs.Contains(treeNode.Id))
allHs.Add(treeNode.Id, treeNode);
}
else
{
if (parenths.Contains(treeNode.ParentId))
{
//如果父亲节点在顶级节点中存在,则添加到顶级节点的孩子表中,并保存在已建树的hashtable中
parentTreeNode = (ITreeNode)parenths[treeNode.ParentId];
if (!allHs.Contains(treeNode.Id))
{
allHs.Add(treeNode.Id, treeNode);
parentTreeNode.Children.Add(treeNode);
}
}
else
{
//如果父亲节点不在顶级节点了,则找到父亲节点,反向向上递归,直到找到顶级节点
parentTreeNode = (ITreeNode)_hs[treeNode.ParentId];
if (!allHs.Contains(treeNode.Id))
{
allHs.Add(treeNode.Id, treeNode);
parentTreeNode.Children.Add(treeNode);
}
InitTreeNode(parentTreeNode, parenths, allHs);
}
}
}
}
public class Tree
{
private Hashtable _hs;
public Tree(Hashtable hs)
{
if (hs == null)
throw new Exception("the hashtabe is null in Create tree");
_hs = hs;
}
public ArrayList CreateTree()
{
Hashtable parenths = new Hashtable();//保存顶级父亲节点
Hashtable allNodes = new Hashtable();//保存已经添加到树结构的节点
foreach (DictionaryEntry entry in _hs)
{
if (allNodes.Contains(entry.Key))
continue;
if (entry.Value is ITreeNode)
InitTreeNode((ITreeNode)entry.Value, parenths, allNodes);
}
ArrayList roots = new ArrayList();
//将顶级节点添加到roots中
foreach (DictionaryEntry entry in parenths)
{
roots.Add(entry.Value);
}
return roots;
}
/**//// <summary>
/// 反向递归建立树结构
/// </summary>
/// <param name="treeNode">树节点</param>
/// <param name="parenths">保存顶级节点的hashtable</param>
/// <param name="allHs">已经建立节点的hashtable</param>
private void InitTreeNode(ITreeNode treeNode, Hashtable parenths, Hashtable allHs)
{
ITreeNode parentTreeNode;
//如果treenode已经添加,则返回不做任何操作
if (allHs.Contains(treeNode.Id))
return;
if (treeNode.ParentId == "0" || !_hs.Contains(treeNode.ParentId))
{
//如果treenode不存在父节点,则被认为顶级节点
if (!parenths.Contains(treeNode.Id))
parenths.Add(treeNode.Id, treeNode);
if (!allHs.Contains(treeNode.Id))
allHs.Add(treeNode.Id, treeNode);
}
else
{
if (parenths.Contains(treeNode.ParentId))
{
//如果父亲节点在顶级节点中存在,则添加到顶级节点的孩子表中,并保存在已建树的hashtable中
parentTreeNode = (ITreeNode)parenths[treeNode.ParentId];
if (!allHs.Contains(treeNode.Id))
{
allHs.Add(treeNode.Id, treeNode);
parentTreeNode.Children.Add(treeNode);
}
}
else
{
//如果父亲节点不在顶级节点了,则找到父亲节点,反向向上递归,直到找到顶级节点
parentTreeNode = (ITreeNode)_hs[treeNode.ParentId];
if (!allHs.Contains(treeNode.Id))
{
allHs.Add(treeNode.Id, treeNode);
parentTreeNode.Children.Add(treeNode);
}
InitTreeNode(parentTreeNode, parenths, allHs);
}
}
}
}
3 测试
Code
private void btnTree_Click(object sender, EventArgs e)
{
Hashtable hs = new Hashtable();
hs.Add("1", new Region("1", "0", "福建"));
hs.Add("2", new Region("2", "1", "福州"));
hs.Add("3", new Region("3", "1", "厦门"));
hs.Add("4", new Region("4", "2", "鼓楼"));
hs.Add("5", new Region("5", "0", "湖南"));
hs.Add("6", new Region("6", "5", "长沙"));
hs.Add("7", new Region("7", "0", "上海"));
hs.Add("8", new Region("8", "0", "北京"));
Tree tree = new Tree(hs);
this.Controls.Add(InitTreeView(tree.CreateTree()));
}
private void btnTree_Click(object sender, EventArgs e)
{
Hashtable hs = new Hashtable();
hs.Add("1", new Region("1", "0", "福建"));
hs.Add("2", new Region("2", "1", "福州"));
hs.Add("3", new Region("3", "1", "厦门"));
hs.Add("4", new Region("4", "2", "鼓楼"));
hs.Add("5", new Region("5", "0", "湖南"));
hs.Add("6", new Region("6", "5", "长沙"));
hs.Add("7", new Region("7", "0", "上海"));
hs.Add("8", new Region("8", "0", "北京"));
Tree tree = new Tree(hs);
this.Controls.Add(InitTreeView(tree.CreateTree()));
}
附上源码,大家可以调式看下
Happy Everyday
beldy