So, the first thing we want to do is take our lines and turn them into a tree. Once we have a tree, matching these nodes with a TreeView pretty simple.
We start by defining the tree itself:
public class Node<T> { public Node(T value, IEnumerable<Node<T>> children) { Value = value; Children = children; } public T Value { get; private set; } public IEnumerable<Node<T>> Children { get; private set; } }
Pleasant and easy, each node is simply a meaning and a collection of children.
Next, we will write a method to take a sequence of sequences and construct a tree from it. The idea here is that we will group all the elements based on the first value in their sequence, build a node for each group, and then recursively call the method in the group to get the children for this node.
public static IList<Node<T>> GroupToTree<T>(this IEnumerable<IEnumerable<T>> source) { return GroupToTree(source.Select(sequence => sequence.GetEnumerator())); } private static IList<Node<T>> GroupToTree<T>(IEnumerable<IEnumerator<T>> source) { return source.WhereHasNext() .GroupBy(iterator => iterator.Current) .Select(group => new Node<T>(group.Key, GroupToTree(group))) .ToList(); }
Now we can take the raw data, split each of the lines into a sequence of lines, and then match each of the nodes that we have here in the nodes based on the UI for presentation:
List<string> rawData = new List<string>(); //TODO populate raw data Func<Node<string>, TreeNode> selector = null; selector = node => new TreeNode(node.Value, node.Children.Select(selector).ToArray()); var nodes = rawData.Select(line => line.Split('_').AsEnumerable()) .GroupToTree() .Select(selector);
Servy source share