PotatoBox
PotatoBox

Reputation: 608

StatusStripLabel dynamically updated

My point is to display number of all child nodes at StatusStripLabel. My point is that I want StatusStripLabel to get updated everytime number of child nodes get's changed - I'll add or delete some of already exists. First, I placed code in Public Form, but it didn't worked as I expected. After some time I came with idea that actually works: I placed the code inside button method. But after that I realized that I'll need to place it in second place, in case of deleting node. So My question is: is there anything that can make it simplier? If my explanation isn't enough, just tell me, I'll try my best.

Code from Public Form (Because I want that counter to work from the beggining, not after I'll press the button)

childNodeCounter();
toolStripStatusLabel1.Text = "Number of games in database: " + NodeCounter.ToString();

Method:

        public void childNodeCounter()
    {
        NodeCounter = 0;
        foreach (TreeNode RootNode in treeView1.Nodes)
        {

            foreach (TreeNode ChildNode in RootNode.Nodes)
            {
                NodeCounter++;
            }
        }
        toolStripStatusLabel1.Text = "Number of games in database: " + NodeCounter.ToString();

    }

Code inside button method:

    private void button1_Click(object sender, EventArgs e)
    {

        NodeCounter = 0;
        foreach (TreeNode RootNode in treeView1.Nodes)
        {

            foreach (TreeNode ChildNode in RootNode.Nodes)
            {
                NodeCounter++;
            }
        }
        toolStripStatusLabel1.Text = "Number of games in database: " + NodeCounter.ToString();
    }

Edit: Thanks to mr. Hans Passant I wrote this and it works very well:

        public int childNodeCounter(TreeNodeCollection nodes)
        {
        int count = 0;
        foreach (TreeNode RootNode in nodes)
        {
            foreach (TreeNode ChildNode in RootNode.Nodes)
                count++;
        }
        return count;

Event handler looks like this:

toolStripStatusLabel1.Text = "Number of games in database: " + childNodeCounter(treeView1.Nodes);

Upvotes: 0

Views: 140

Answers (3)

Bojan Komazec
Bojan Komazec

Reputation: 9526

If you're adding and removing "game" nodes to the treeView, you must be having methods like void AddGame(string title) and void RemoveGame(string title) which add/remove (child) nodes - those whose total number you want to count. If I understood well, you want toolStripStatusLabel1.Text to be automatically updated each time the number of child nodes changes. In that case you can add field

private int nodesCount;

to your Form class and have something like this:

void AddGame(string title)
{
    if(InvokeRequired)
    {
        Invoke(new MethodInvoker(delegate() { AddGame(title); }));
    }
    else
    {
        AddGameNodeToTreeView(title); // add new game node to desired place in TreeView
        nodesCount++; // increase node counter
        toolStripStatusLabel1.Text = "Number of games in database: " + nodesCount;
    }  
}

RemoveGame() would be implemented in the same way (or joined with AddGame() into a single method with one additional argument - bool add). Both methods could be extended if you're adding/removing multiple nodes in which case you'll be passing title array and updating nodesCount accordingly.

The advantage of this approach is that you don't have to count nodes in the tree each time before updating toolStripStatusLabel1.Text. Also, toolStripStatusLabel1.Text is updated automatically, not only when user clicks the button.

Drawback is that nodesCount is somewhat redundant information: total number of nodes of interest is 'hidden' in the treeView. You have to make sure that nodesCount is in sync with the actual number of nodes.

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 941635

The natural way to traverse a tree structure is by using recursion. That's always a bit hard to reason through but there are lots of resources available. Doing it iteratively is a lot uglier, you have to use a Stack<> to allow you to backtrack again out of a nested node. I'll therefore post the recursion solution:

    private static int CountNodes(TreeNodeCollection nodes) {
        int count = nodes.Count;
        foreach (TreeNode node in nodes) count += CountNodes(node.Nodes);
        return count;
    }

Then your event handler becomes:

    private void button1_Click(object sender, EventArgs e) {
        toolStripStatusLabel1.Text = "Number of games in database: " +
            CountNodes(treeView1.Nodes);
    }

Upvotes: 1

Curt
Curt

Reputation: 5722

Three tiny optimizations

  1. Rather that iterate the tree yourself, just use ChildNode.Nodes.GetNodeCount

  2. Rather than repeat the same logic in different places, have your button Click events simply call the UpdateNodeCount() method.

  3. The text initializer in the first code fragment is redundant, and can be eliminated: the call to childNodeCounter already does the status label update.

Upvotes: 1

Related Questions