简体   繁体   中英

Follow-Up: Finding the Child of a Control

I believe the proper term is recursively . I have a Windows Form, and inside that I have a Tab Control, and inside the Tab Control are four Tabs, and inside each tab are multiple controls - Buttons, text boxes, etc. I want to change the cursor of every button to a type hand.

Below is where I have gotten so far with this inquiry:

foreach (Control c in tabControl1.Controls)
         {

             // The only controls that will be found here are the tabs themselves. So, now I must run a *foreach* loop through every tab found, and look if buttons are present.

         }

The commented area explains my issue to some extent. I have found an example of a recurisively finding a control on a form but I am not sure why I would need to pass the contro's name as an argument as I am trying to find Every control of type button.

Here is the code that I found online: http://www.dreamincode.net/code/snippet1663.htm

Thank you once again. I love hearing from all of you as it's an excellent learning experience for me.

Thank you very much for your time.

private void FindAll(Control myControl)
{
    if (myControl is Button)
        doStuff();

    foreach (Control myChild in myControl.Controls)            
        FindAll(myChild);

}

I believe this will work. When you call it the first time, you'd pass in the form. The form isn't a button, but it will have children. Each child it has will be passed into FindAll(). If that control is a button, it will call doStuff() (you can set the cursor in there). Likewise if that control has any children, they'll be passed in.

You are correct, the term is recurisve (generally speaking, any function or sub that calls itself). So, in this example FindAll() will call FindAll() in a certain case.

Also, this is just sample code; you may want to check for null references depending on the nature of your application.

EDIT: Just as an FYI if you aren't familiar with recursion, it's pretty easy to get the dreaded StackOverflow exception. When you end up in a never-ending loop of calling yourself, you'll run out of stackspace and see the StackOverflow exception. Hence, the name www.StackOverflow.com

In this case, we don't have to worry because .NET prevents us from adding controls that create a circular reference. For example - this code will fail:

    GroupBox g1 = new GroupBox();
    GroupBox g2 = new GroupBox();
    GroupBox g3 = new GroupBox();

    g1.Controls.Add(g2);
    g2.Controls.Add(g3);
    g3.Controls.Add(g1);

I don't know if any of this makes sense, but hopefully it helps. Recursion is generally considered one of the 'harder' concepts to grasp for a lot of people. Then again, I'm not very good at explaining things.

You are correct that the correct term is recursion. In the link you have posted, it is indeed recursive because the function calls itself, which is a property common of recursive functions.

The function needs to take a Control instance because the function is trying to solve the problem "For a given control (which is the Control container that is passed in), find all controls inside." Notice how this method doesn't care about what 'level' the control is at, it can solve it regardless.

You are correct that if you ran the code in your example, it would not work. It would only pick up controls one level inside of the 'parent' control. This is why the function needs to call itself.

With the function calling itself, you get the following:

Call function with the outermost control.
Do I have any children?
If so, call the same function again for each child (which will again ask "Do I have any children?" on the child).

By calling the function inside the function, you will hit all levels.

WARNING: Just as a note of caution, recursion used carelessly can lead to problems. If you apply this on something that has 1000 'levels', your algorithm will take forever and possibly crash as you will run out of memory to handle it, since it is digging deeper and deeper (a stack overflow!). Separately, I suspect there is a better way to do what you are doing such that you don't need to use recursion, although it will work.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM