在树结构上实现IEnumerable

根据这些家伙的工作:

  • http://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/
  • http://www.matthidinger.com/archive/2009/02/08/asp.net-mvc-recursive-treeview-helper.aspx

我正在尝试实现一个可以这样使用的TreeView助手:

 r.Children, r => r.ID) %> 

树结构的定义如下:

 public class Tree : TreeNode where T : TreeNode { } public class TreeNode : IDisposable where T : TreeNode { public T Parent { get; set; } public TreeNodeList Children { get; set; } } public class TreeNodeList : List<TreeNode> where T : TreeNode { public T Parent; public T Add(T node) { base.Add(node); node.Parent = (T)Parent; return node; } public void Remove(T node) { if (node != null) node.Parent = null; base.Remove(node); } } 

TreeView助手有这个签名:

 public static string TreeView(this HtmlHelper htmlHelper, string treeId, IEnumerable rootItems, Func<T, IEnumerable> childrenProperty, Func itemContent, bool includeJavascript, string emptyContent) { ... } 

因此,我需要我的Tree struture来实现IEnumerable,所以我可以将它与TreeView帮助器一起使用,这导致了一个问题:在这种情况下我将在何处以及如何实现IEnumerable?

对于想要实现递归树迭代器的人来说,Wes Dyer的这篇文章很好读:

http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx

我不完全理解树结构的确切细节,但这是一个简单的实现,它采用通用的节点树并递归地将其呈现为html列表。

 public static string TreeView(IEnumerable rootItems, Func> childrenProperty, Func itemContent) { if (rootItems == null || !rootItems.Any()) return null; var builder = new StringBuilder(); builder.AppendLine("
    "); foreach (var item in rootItems) { builder.Append("
  • ").Append(itemContent(item)).AppendLine("
  • "); var childContent = htmlHelper.TreeView(treeId, childrenProperty(item), childrenProperty, itemContent); if (childContent != null) { var indented = childContent.Replace(Environment.NewLine, Environment.NewLine + " "); builder.Append(" ").AppendLine(indented); } } builder.Append("
"); return builder.ToString(); }

我正在使用的节点类相对简单,只有两个属性。

 public class Node { public Node(T data) { Data = data; Children = new List>(); } public T Data { get; private set; } public ICollection> Children { get; private set; } } 

这是一些将树输出到控制台的测试代码。

 var Records = new[] { new Node("one") { Children = { new Node("one-one") { Children = { new Node("one-one-one"), new Node("one-one-two"), new Node("one-one-three") } }, new Node("one-two"), new Node("one-three") } }, new Node("two"), new Node("three") }; Console.WriteLine(TreeView(Records, r => r.Children, r => r.Data)); 

以下是上述代码的结果。

 
  • one
  • one-one
  • one-one-one
  • one-one-two
  • one-one-three
  • one-two
  • one-three
  • two
  • three