How do I loop through all layers of Treeview nodes?

21,341

Solution 1

Recursion?

Edit: added code for eliminating color repetition

protected void ColorNodes(TreeNode root, Color firstColor, Color secondColor)
{
   Color nextColor;
   foreach (TreeNode childNode in root.Nodes)
   {     
      nextColor = childNode.ForeColor = childNode.Index % 2 == 0 ? firstColor : secondColor;

      if (childNode.Nodes.Count > 0)
      {
         // alternate colors for the next node
         if (nextColor == firstColor)
              ColorNodes(childNode, secondColor, firstColor);
         else
              ColorNodes(childNode, firstColor, secondColor);
      }
   }
}

  private void frmCaseNotes_Load(object sender, System.EventArgs e)
    {
       foreach (TreeNode rootNode in treeView1.Nodes)
       {
          ColorNodes(rootNode, Color.Goldenrod, Color.DodgerBlue);
       }
    }

Solution 2

Dude, this one was serious trouble. The Broadth Search was easy, but you were right. Depth Search was a pain. I hope it helps you. Shame that such nice trick will probably fall into oblivion due to the sheer ammount of questions on this site. The depth algorithm is kind of crude and assume a head node without siblings.

//depth search on TreeView

TreeNode node = trv.Nodes[0];
Stack<TreeNode> list = new Stack<TreeNode>();
list.Push(node);

while (list.Count > 0)
{
    while (node.Nodes.Count > 0)
    {
        list.Push(node.Nodes[0]);
        node = node.Nodes[0];
    }

    //Will always have a leaf here as the current node. The leaf is not pushed.
    //If it has a sibling, I will try to go deeper on it.
    if (node.NextNode != null)
    {
        node = node.NextNode;
        continue;
    }

    //If it does NOT have a sibling, I will pop as many parents I need until someone
    //has a sibling, and go on from there.
    while (list.Count > 0 && node.NextNode == null)
    {
        node = list.Pop();
    }
    if (node.NextNode != null) node = node.NextNode;
}

//broadth search on TreeView

Queue<TreeNode> list = new Queue<TreeNode>();
foreach(TreeNode node in trv.Nodes)
{
    list.Enqueue(node);
}
foreach(TreeNode node in list)
{
    foreach(TreeNode childNode in node.Nodes)
    {
        list.Enqueue(childNode);
    }
}

Solution 3

The best way to do this would be to override the OnPaint event, and provide your own code for drawing in the control.

You can find many examples on overriding the onPaint method online.

EDIT: I actually looked into this some more, and you can set the BackColor of treeview nodes individually already.

Me.TreeView1.Nodes(0).BackColor = Color.AliceBlue  
Share:
21,341
Refracted Paladin
Author by

Refracted Paladin

My Philosophy

Updated on April 14, 2020

Comments

  • Refracted Paladin
    Refracted Paladin about 4 years

    Read EDIT 2 first

    I am trying to set up some way to visually distinguish the nodes in a winform app. For example, alternating colors.

    Can some one start me down that path? Also, has anyone else had to do that before and how did you do it?

    Thanks

    EDIT

    I had seen the backcolor setting as well(Thank You) but I am having trouble getting it to work. I do not see a Paint() event for treeviews. I tried putting the below code in my Form Load() but it isn't working. Possibly because the treeview is loaded yet??

            private void frmCaseNotes_Load(object sender, System.EventArgs e)
        {
            foreach (TreeNode treeNode in treeView1.Nodes[0].Nodes)
            {
                treeNode.BackColor = Color.DeepSkyBlue;
            }
        }
    

    EDIT 2

    Okay, I have the initial problem out of the way using the below on Form_Load()

                foreach (TreeNode treeNode in treeView1.Nodes)
            {
                if (treeNode.Index % 2 == 0)
                {
                     treeNode.ForeColor = Color.DodgerBlue;
                }
                else
                {
                    treeNode.ForeColor = Color.Goldenrod;
                }
    

    Now what I need to figure out, with someone's help, is how to Loop through ALL layers of nodes and apply my alternating coloring. If I do something along the below lines I can achieve this.

                foreach (TreeNode treeNode in treeView1.Nodes[1].Nodes[0].Nodes)
            {
                if (treeNode.Index % 2 == 0)
                {
                     treeNode.ForeColor = Color.DodgerBlue;
                }
                else
                {
                    treeNode.ForeColor = Color.Goldenrod;
                }
    

    How do I iterate through ALL layers programatically?

  • Refracted Paladin
    Refracted Paladin about 15 years
    This is close enough to count. I will figure the rest out and post it here for archival purposes. Thanks for the help!