Using C#, I have created a "node" class (which contains a List of type itself) to allow for recursive tree-like data structures. This is a simplified version of the class:
public class node
{
public List<node> c = null;
public int data = 0;
public node(int data)
{
this.data = data;
}
}
Unfortunately, I've come across a point in my program where it's getting very hard to debug due to the nature of trees. Large trees especially are difficult to probe visually.
For this reason, I had the brain wave to use Winform's TreeView control to display the data so I can more easily visualize what's going on. I understand and have implemented preorder and inorder traversal for a minimax algorithm, and so I was wondering if I could utilize some of that code to help with converting from my own node tree to a TreeView tree.
The method skeleton would look like this:
private void convertNodetreetoTreeview(node n)
{
TreeNode root = new TreeNode("Root node");
...
treeView1.Nodes.Add(root);
}
How would I go about this?
For speed, I would prefer an iterative solution, but a recursive solution would be fine too.
CodePudding user response:
Below is the code to go about just what you're asking for. Instead of utilizing a Stack and a List (as you might for usual preorder traversal), you utilize TWO stacks - one for the node tree you have, and one for the TreeView tree. From there, it's a simple case of pushing TreeView nodes when custom nodes are being pushed, and popping TreeView nodes when your custom nodes are being popped. Whilst you're pushing TreeView nodes, you simultaneously add these nodes to the TreeView using the top-most TreeView stack reference.
Feel free to replace the mystringdata variable with one of your choice.
private void convertNodetreeToTreeview(node n)
{
Stack<node> stack1 = new Stack<node>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
stack1.Push(n);
TreeNode root = new TreeNode( n.mystringdata );
stack2.Push(root);
while (stack1.Count > 0)
{
node t = stack1.Pop();
TreeNode r = stack2.Pop();
for (int i = 0; i < t.c.Count; i )
{
if (t.c[i] != null)
{
stack1.Push(t.c[i]);
TreeNode rchild = new TreeNode(t.c[i].mystringdata );
r.Nodes.Add(rchild);
stack2.Push(rchild);
}
}
}
treeView1.Nodes.Add(root);
}
CodePudding user response:
I take the following statement and as I mentioned in the comments, as an idea you can also 
And if you click on it, you can see your custom visualizer, which could be a Form containing a TreeView:
Create a custom debugger visualizer for my tree-like data structure
There are a few nice articles and guides in Microsoft Docs which explains the architecture of the visualizers and teach you how to create an install a simple visualizer. Here I also put a very simplified guideline to show you how you can achieve what I showed in above screenshots:
Create a .NET Framework Class Library for you data class. Name the project
MyDataObjects. This project will contain your data objects which you want to create a custom visualizer for them. Here,Nodeclass. Use the same node class in your main project as well.Add the following
Node.csclass to it:using System; using System.Collections.Generic; namespace MyDataObjects { [Serializable] public class Node { private Node() { } public List<Node> Nodes { get; } = new List<Node>(); public string Text { get; set; } public Node(string data) { this.Text = data; } } }Create a .NET Framework Class Library for you visualizer. Name the project
MyDataObjectsVisualizers.Add reference to
Microsoft.VisualStudio.DebuggerVisualizers.dllwhich you can browse from:
<Visual Studio Install Directory>\Common7\IDE\PublicAssemblies
Add reference to
System.Windows.Forms.dllwhich you can find in framework assemblies.Add the following
NodeExtensions.csclass to it:using MyDataObjects; using System.Windows.Forms; namespace MyDataObjectsVisualizers { public static class NodeExtensions { public static TreeNode ToTreeNode(this Node node) { var treeNode = new TreeNode(node.Text); foreach (Node child in node.Nodes) treeNode.Nodes.Add(child.ToTreeNode()); return treeNode; } } }Add a new form to the project and name it
NodeVisualizerForm.cs. Drop aTreeViewon the form and set itsDocktoFill. Then add the following code to the form:using MyDataObjects; using System; using System.Windows.Forms; namespace MyDataObjectsVisualizers { public partial class NodeVisualizerForm : Form { public NodeVisualizerForm() { InitializeComponent(); } public Node Node { get; set; } protected override void onl oad(EventArgs e) { base.OnLoad(e); if (Node != null) treeView1.Nodes.Add(Node.ToTreeNode()); } } }Add a
DebuggerSide.csclass to the project with the following code:using Microsoft.VisualStudio.DebuggerVisualizers; [assembly: System.Diagnostics.DebuggerVisualizer( typeof(MyDataObjectsVisualizers.DebuggerSide), typeof(VisualizerObjectSource), Target = typeof(MyDataObjects.Node), Description = "Sample Visualizer")] namespace MyDataObjectsVisualizers { public class DebuggerSide : DialogDebuggerVisualizer { protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) { var node = objectProvider.GetObject() as MyDataObjects.Node; var form = new NodeVisualizerForm(); form.Node = node; windowService.ShowDialog(form); } } }Build the solution, and copy the following files to the following locations:
- Copy
MyDataObjectsVisualizers.dllto:
[VS Installation Folder]\Common7\Packages\Debugger\Visualizers - Copy
MyDataObjects.dllto:
[VS Installation Folder]\Common7\Packages\Debugger\Visualizers\netstandard2.0
- Then close all visual studio instances. Then open the solution which you ant to debug and set a breakpoint for node, and run the application. There you go! You can see the visualizer icon (the magnifier) close to the node, like what I showed in the screenshot above and by clicking on it, you will see the visualizer form.
Please take note, in the main project, you should use the same Node dll that we created in MyDataObjects project.
More information:
CodePudding user response:
To convert a custom node class to a TreeNode, you can write a simple recursive extension method.
Assuming you have a class like this:
public class Node
{
public List<Node> Nodes { get; } = new List<Node>();
public string Text { get; set; }
public Node(string data)
{
this.Text = data;
}
}
Then you can write a simple recursive extension method like the following:
public static class NodeExtensions
{
public static TreeNode ToTreeNode(this Node node)
{
var treeNode = new TreeNode(node.Text);
foreach (Node child in node.Nodes)
treeNode.Nodes.Add(child.ToTreeNode());
return treeNode;
}
}
Later, to use it to populate a TreeView:
var node = new Node("1");
node.Nodes.Add(new Node("1-1"));
node.Nodes.Add(new Node("1-2"));
node.Nodes[0].Nodes.Add(new Node("1-1-1"));
node.Nodes[1].Nodes.Add(new Node("1-2-1"));
node.Nodes[1].Nodes.Add(new Node("1-2-2"));
treeView1.Nodes.Add(node.ToTreeNode());
To see a general solution to populate a TreeView based on a DataTable or any list which contains tree-like data, take a look at: Populate TreeView from DataTable or List that contains tree-like data
More information:

