One week ago, I surfed a forum and got a tree class template. It has some a little diffrence from what I knew before. I used this class template to deal with a work task. Spending two hours,I just understood what its conception.
Original Class Code:
代码
public delegate void TreeVisitor<T>(T nodeData);
public class NTree<T>
{
public T data;
LinkedList<NTree<T>> children;
public NTree(T data)
{
this.data = data;
children = new LinkedList<NTree<T>>();
}
public void addChild(T data)
{
children.AddFirst(new NTree<T>(data));
}
public NTree<T> getChild(int i)
{
foreach (NTree<T> n in children)
if (--i == 0) return n;
return null;
}
public void traverse(NTree<T> node, TreeVisitor<T> visitor)//here is visitor pattern
{
visitor(node.data);
foreach (NTree<T> kid in node.children)
traverse(kid, visitor);
}
}
public class NTree<T>
{
public T data;
LinkedList<NTree<T>> children;
public NTree(T data)
{
this.data = data;
children = new LinkedList<NTree<T>>();
}
public void addChild(T data)
{
children.AddFirst(new NTree<T>(data));
}
public NTree<T> getChild(int i)
{
foreach (NTree<T> n in children)
if (--i == 0) return n;
return null;
}
public void traverse(NTree<T> node, TreeVisitor<T> visitor)//here is visitor pattern
{
visitor(node.data);
foreach (NTree<T> kid in node.children)
traverse(kid, visitor);
}
}
I Created a node data clas
代码
public class NodeData
{
string _text = null;
public string Text
{
get { return _text; }
set { _text = value; }
}
string _url = null;
public string Url
{
get { return _url; }
set { _url = value; }
}
int? _id = null;
public int? Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 0-root
/// 1-channel
/// 2-column
/// </summary>
int? _type = null;
public int? Type
{
get { return _type; }
set { _type = value; }
}
int? _parentId = null;
public int? ParentId
{
get { return _parentId; }
set { _parentId = value; }
}
}
{
string _text = null;
public string Text
{
get { return _text; }
set { _text = value; }
}
string _url = null;
public string Url
{
get { return _url; }
set { _url = value; }
}
int? _id = null;
public int? Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// 0-root
/// 1-channel
/// 2-column
/// </summary>
int? _type = null;
public int? Type
{
get { return _type; }
set { _type = value; }
}
int? _parentId = null;
public int? ParentId
{
get { return _parentId; }
set { _parentId = value; }
}
}
My points are first traverse a tree to generate its nodes and then traverse it to create a menu for default page .
代码
public class Navigator
{
protected NTree<NodeData> node;//represent
protected void CreataNavigatorTree()
{
TreeVisitor<NodeData> TreeVisitor = TreeCreate;
NodeData rootData = new NodeData();
rootData.Text = "root";
rootData.Url = null;
rootData.Type = 0;
node = new NTree<NodeData>(rootData);
node.traverse(node, TreeVisitor);//Create Tree
}
void TreeCreate<T>(T TNode)
{
NodeData data = TNode as NodeData;
if (data.Type == 0)
{
IList<KyChannel> lstChan = KyChannel.GetAll();
foreach (KyChannel chan in lstChan)
{
NodeData newdata = new NodeData();
newdata.Text = chan.ChName;
newdata.Url = "/Channel.aspx?ChId=" + chan.ChId;
newdata.Id = chan.ChId;
newdata.Type = 1;
newdata.ParentId = 0;
node.addChild(newdata);// add channels
NTree<NodeData> thisChildNode = node.getChild(1); //get this channel node
foreach (Zybw.Cms.Addition.Entity.KyColumn kc in chan.KyColumn)
{
newdata = new NodeData();
newdata.Text = kc.ColName;
newdata.Url = "/Column.aspx?ColId=" + kc.ColId + "&P=0";
newdata.Id = kc.ColId;
newdata.Type = 2;
newdata.ParentId = thisChildNode.data.Id;
thisChildNode.addChild(newdata);// add columns for each channels
}
}
}
else if (data.Type == 1)
{
}
else if (data.Type == 2)
{
IList<KyColumn> lstCols = GetChildColumns((int)data.Id);
foreach (KyColumn kc in lstCols)
{
NodeData newdata = new NodeData();
newdata.Text = kc.ColName;
newdata.Url = "/Column.aspx?ColId=" + kc.ColId + "&P=0";
newdata.Id = kc.ColId;
newdata.Type = 2;
newdata.ParentId = node.data.Id;
node.addChild(newdata);// add child columns for each columns
}
}
}
IList<KyColumn> GetChildColumns(int id)
{
IList<KyColumn> lstCol = Zybw.Cms.Addition.Entity.KyColumn.GetByConditon(c => c.ColParentId == id);
return lstCol;
}
protected virtual void CreateNav()
{
CreataNavigatorTree();
TreeVisitor<NodeData> TreeVisitor = NavigatorItemsCreate;
node.traverse(node, TreeVisitor);
navBuilder = navBuilder.Replace("channels", channelBuilder.ToString());
foreach (int key in columCollection.Keys)
{
navBuilder = navBuilder.Replace("col" + key.ToString(), columCollection[key]);
}
//Add css
System.Web.UI.Page page = System.Web.HttpContext.Current.Handler as System.Web.UI.Page;
string css = "<link href=\"" + page.Request.ApplicationPath + "nav/css/nav.css\" type=\"text/css\" rel=\"stylesheet\" />";
navBuilder.Append(css, 0, css.Length);
_nav = navBuilder.ToString();
//remove none columns
string sPattern = "col\\d{1}";
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(sPattern);
_nav = reg.Replace(_nav, "");
}
string _nav = null;
public string Nav
{
get
{
CreateNav();
return _nav;
}
}
StringBuilder navBuilder = new StringBuilder();
StringBuilder channelBuilder = new StringBuilder();
Dictionary<Int32, string> columCollection = new Dictionary<Int32, string>();
void NavigatorItemsCreate<T>(T TNode)
{
NodeData data = TNode as NodeData;
switch (data.Type)
{
case 0:
navBuilder.AppendFormat("<div class=\"menu\"><ul>channels</ul></div>");
break;
case 1:
channelBuilder.AppendFormat("<li><a class=\"drop\" href=\"{0}\">{1}<!--[if IE 7]><!--></a><!--<![endif]--><table><tr><td><ul>col{2}</li></ul></td></tr></table><!--[if lte IE 6]></a><![endif]-->", data.Url, data.Text, data.Id.ToString());
break;
case 2:
StringBuilder level1Builder = new StringBuilder();
level1Builder.AppendFormat("<li><a href=\"{0}\" title=\"{1}\">{2}</a></li>", new string[3] { data.Url, data.Text, data.Text });
if (columCollection.Keys.Where(c => c == data.ParentId).Count() != 1)
columCollection.Add((int)data.ParentId, level1Builder.ToString());
else
columCollection[(int)data.ParentId] = columCollection[(int)data.ParentId] + level1Builder.ToString();
break;
}
}
}
{
protected NTree<NodeData> node;//represent
protected void CreataNavigatorTree()
{
TreeVisitor<NodeData> TreeVisitor = TreeCreate;
NodeData rootData = new NodeData();
rootData.Text = "root";
rootData.Url = null;
rootData.Type = 0;
node = new NTree<NodeData>(rootData);
node.traverse(node, TreeVisitor);//Create Tree
}
void TreeCreate<T>(T TNode)
{
NodeData data = TNode as NodeData;
if (data.Type == 0)
{
IList<KyChannel> lstChan = KyChannel.GetAll();
foreach (KyChannel chan in lstChan)
{
NodeData newdata = new NodeData();
newdata.Text = chan.ChName;
newdata.Url = "/Channel.aspx?ChId=" + chan.ChId;
newdata.Id = chan.ChId;
newdata.Type = 1;
newdata.ParentId = 0;
node.addChild(newdata);// add channels
NTree<NodeData> thisChildNode = node.getChild(1); //get this channel node
foreach (Zybw.Cms.Addition.Entity.KyColumn kc in chan.KyColumn)
{
newdata = new NodeData();
newdata.Text = kc.ColName;
newdata.Url = "/Column.aspx?ColId=" + kc.ColId + "&P=0";
newdata.Id = kc.ColId;
newdata.Type = 2;
newdata.ParentId = thisChildNode.data.Id;
thisChildNode.addChild(newdata);// add columns for each channels
}
}
}
else if (data.Type == 1)
{
}
else if (data.Type == 2)
{
IList<KyColumn> lstCols = GetChildColumns((int)data.Id);
foreach (KyColumn kc in lstCols)
{
NodeData newdata = new NodeData();
newdata.Text = kc.ColName;
newdata.Url = "/Column.aspx?ColId=" + kc.ColId + "&P=0";
newdata.Id = kc.ColId;
newdata.Type = 2;
newdata.ParentId = node.data.Id;
node.addChild(newdata);// add child columns for each columns
}
}
}
IList<KyColumn> GetChildColumns(int id)
{
IList<KyColumn> lstCol = Zybw.Cms.Addition.Entity.KyColumn.GetByConditon(c => c.ColParentId == id);
return lstCol;
}
protected virtual void CreateNav()
{
CreataNavigatorTree();
TreeVisitor<NodeData> TreeVisitor = NavigatorItemsCreate;
node.traverse(node, TreeVisitor);
navBuilder = navBuilder.Replace("channels", channelBuilder.ToString());
foreach (int key in columCollection.Keys)
{
navBuilder = navBuilder.Replace("col" + key.ToString(), columCollection[key]);
}
//Add css
System.Web.UI.Page page = System.Web.HttpContext.Current.Handler as System.Web.UI.Page;
string css = "<link href=\"" + page.Request.ApplicationPath + "nav/css/nav.css\" type=\"text/css\" rel=\"stylesheet\" />";
navBuilder.Append(css, 0, css.Length);
_nav = navBuilder.ToString();
//remove none columns
string sPattern = "col\\d{1}";
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(sPattern);
_nav = reg.Replace(_nav, "");
}
string _nav = null;
public string Nav
{
get
{
CreateNav();
return _nav;
}
}
StringBuilder navBuilder = new StringBuilder();
StringBuilder channelBuilder = new StringBuilder();
Dictionary<Int32, string> columCollection = new Dictionary<Int32, string>();
void NavigatorItemsCreate<T>(T TNode)
{
NodeData data = TNode as NodeData;
switch (data.Type)
{
case 0:
navBuilder.AppendFormat("<div class=\"menu\"><ul>channels</ul></div>");
break;
case 1:
channelBuilder.AppendFormat("<li><a class=\"drop\" href=\"{0}\">{1}<!--[if IE 7]><!--></a><!--<![endif]--><table><tr><td><ul>col{2}</li></ul></td></tr></table><!--[if lte IE 6]></a><![endif]-->", data.Url, data.Text, data.Id.ToString());
break;
case 2:
StringBuilder level1Builder = new StringBuilder();
level1Builder.AppendFormat("<li><a href=\"{0}\" title=\"{1}\">{2}</a></li>", new string[3] { data.Url, data.Text, data.Text });
if (columCollection.Keys.Where(c => c == data.ParentId).Count() != 1)
columCollection.Add((int)data.ParentId, level1Builder.ToString());
else
columCollection[(int)data.ParentId] = columCollection[(int)data.ParentId] + level1Builder.ToString();
break;
}
}
}