Count components in a Groupbox

Jelmer

Regular
Joined
Jan 11, 2006
Messages
96
I've like to build a script that searches for every textbox and cleares it.
The textbox is on a GroupBox.

I've build this script.. but it doesnt work.. it only searches for the main components on the main form. Not the components on the groupbox.

Code:
        private void btnWissen_Click(object sender, EventArgs e)
        {
            foreach (Control tempCtrl in this.Controls)
            {
                string str = Convert.ToString(tempCtrl.GetType());
                if (str == "System.Windows.Forms.TextBox")     
                {
                    tempCtrl.Text = "";
                }
            }
        }

How can i build it like so the program searches al the components on the GroupBox form ?
 
A groupbox is a container object as is a form, you are searching the forms control collection which will only list objects it directly contains i.e. the groupbox. The groupbox then has a control collection. If you wish to access these controls you must search through the groupbox.Controls collection.
 
That's a little less dynamic. Referring to the parent would give you the edge of being able to apply your code to anything...
Visual Basic:
    Private Sub test()
        Dim x As Control
        For Each x In occDate.Parent.Controls
            ....
            ....
        Next
    End Sub
 
I love sample code, so here goes:
C#:
private void btnWissen_Click(object sender, EventArgs e)
{
	ClearTextBoxes(this);
}

private void ClearTextBoxes(Control parent)
{
	foreach (Control childControl in parent.Controls)
	{
		TextBox txt = childControl as TextBox;
		if (txt != null)
		{
			txt.Text = string.Empty;
		}
		else
		{
			ClearTextBoxes(childControl);
		}
	}
}

Untested, but hopefully it works.
I was tempted to optimize a bit and check whether I needed to call ClearTextBoxes(childControl) at all, but figured I'd save that for later if needed. The way it is now, it may call a function and get out right after doing the foreach - you're only saving the push/pop on the stack for a function call and I *hate* thinking about performance at the expense of readability, if the performance doesn't really make much difference.

-ner
 
Well personally I would have done it like so..

C#:
// purely an example of calling the code
private void ClearForm()
{
        ClearTextBoxes(this.Controls);
}

// method for clearing all textboxes based on a recursive method
private void ClearTextBoxes(System.Windows.Forms.Control.ControlCollection container)
{
	foreach(Control ctrl in container)
	{
	        if(ctrl is GroupBox)
		{
			ClearTextBoxes(((GroupBox)ctrl).Controls);
		}
		else if(ctrl is TextBox)
		{
		        ((TextBox)ctrl).Text = string.Empty;
		}
	}
}
 
I don't actually know which method is quicker but Nerseus's would work also, I was half way through typing my reply when his was posted. When I first saw it I thought it would require more validation but as every Control object has a Controls collection it should work fine. I only checked for a groupbox since I forgot that all Control objects have a Controls collection (but its empty for most controls). Whether checking for a goupbox or other true container objects speeds up or slows down the code I have no idea. I would suspect it depends what controls are on the form.
 
I suppose with the current situation (i.e. clearing a bunch of textboxes) speed isn't really an issue. The more important thing is making sure that you've identified the object in the loop as being a text box, otherwise, either an exception will be thrown if the appropriate property isn't available for the class, or you may clear text from another control that you don't want to...

Another useful property of controls is the Tag. You can use this as a kind of indicator, as it will accept any type of object. Set it to something like "CLEARME" and then run through and clear the controls.
 
if we are playing the game 'fastest and shortest'
C#:
private void ClearTextBoxes(Control parent)
{
    foreach (Control ctrl in parent.Controls) ClearTextBoxes(ctrl);
    if (parent is TextBox) parent.Text = string.Empty;
}
 
That is possibly the shortest way the code can be written but I'm not convinced that will always be the fastest. As we were saying before that code will recursively call the method for every control regardless of whether it is likely to have any children. I personally have no idea if it is quicker to call the method and have a loop with no iterations, or to check if the initial object is a true container object.

I did a few quick tests to see which was quicker and found both methods to be comparable in speed, with each one varying slightly depending on the layout of the controls. In the real world its kind of an irrelevant argument because even with 1000's of controls both methods perform in milliseconds, I was just curious.
 
Cags said:
That is possibly the shortest way the code can be written but I'm not convinced that will always be the fastest. As we were saying before that code will recursively call the method for every control regardless of whether it is likely to have any children. I personally have no idea if it is quicker to call the method and have a loop with no iterations, or to check if the initial object is a true container object.
ah yes. . .
[CS] private void ClearTextBoxes(Control parent)
{
foreach (Container ctrl in parent.Controls) ClearTextBoxes(ctrl);
if (parent is TextBox) parent.Text = string.Empty;
}[/CS]
 
Just to reiterate - does it actually matter? Unless you've got hundreds (possibly thousands, depending on the speed of your machine) the user would not be able to tell...
 
Back
Top