Windows Form Control with Children - c#

I have a panel in my Windows form that I would like to add other controls like text boxes into it and also iterate over all elements in the panel to retrieve all the data in it.
Is this possible to do with a panel control?
I experimented with a foreach loop such as
foreach(textbox tb in panel1)
{
}
but I get an error saying panel does not have a public definition for GetEnumerator.
What would be a better control/container to use, where I can add more controls to it and eventually access all the controls within it an their data?
Update
Just a heads up - I am having some problems with adding multiple text boxes in code.
I create a textbox object and then add it to the panel, but only one shows up.
I have read elsewhere on this site and others that adding a textbox with the same name might be causing the problem.
To solve this, I replaced the panel with a flow layout panel which works great.
Hopefully this helps others.

It's the correct control to use. Try iterating the Controls property of the panel object.
foreach(Control control in panel.Controls)
{
if(control is TextBox)
{
TextBox textBox = control as TextBox;
//etc.
}
}

The following example clears all textbox in any control
void ClearTextBoxes(Control parent)
{
foreach (Control child in parent.Controls)
{
TextBox textBox = child as TextBox;
if (textBox == null)
ClearTextBoxes(child);
else
textBox.Text = string.Empty;
}
}
Then whenever you want clear. you call
ClearTextBoxes(panel1);

You need to access Controls collection of the Panel, better if you do:
foreach(Textbox tb in panel1.Controls.OfType<TextBox>)
But the above would give you TextBoxes inside the panel, not inside other controls inside the panel, if you want to get get textboxes recursively then see this question

You're missing one little thing. Try:
foreach (Control c in panel1.Controls)
And then check the control type if you have more than one type of control in it.
The reason for the error is that panel1 is an object, not a collection of objects, so you have to refer specifically to the collection of objects that panel1 contains.

Something like this
foreach (Control c in panel1.Controls)
{
if(c.GetType() == typeof(TextBox))
{
//do stuff
}
}

Related

C# WinForm: Accessing a certain Control in Controls

I have 3 Controls inside a TabPage tabpage1; let's call them panel1, panel2 and datagridview1. I'm trying to make a general method for accessing panel2. How do I access this Panel in TabPage.Controls? I've found out that I can use something like tabpage1.Controls[1]. But how do I know the index of panel2? And how do I set its index?
I believe you can use the controls collection.
var ctrls = this.Controls.Find("ControlName", true);
if (ctrls != null)
if(ctrls.Length != 0)
{
Control ctrl = ctrls[0];
}
I am not good in C# but I believe it works and you can easy make an universal method from it. (this only for the ilustrational purposes - replace with the apriopriate object.

How to remove user control from dock panel

RoomDiagram rd = new RoomDiagram();
maincDockPanel.Children.Remove(rd);
when i wright this nothing happens.
how i can remove child and then add new one? thanks
If you need to remove then you have to use dockPanel1.Children.RemoveAt() because Children is UIElement Collection you may write a small code to ietrate over the collection and see if it is your required control to remove then remove it similarly dockPanel1.Children.Add() to add UIElement same should be the case if you are using UserControl
some sample code to Iterate over collection and will show you the name of the controls
foreach (Control x in dockPanel1.Children)
{
MessageBox.Show(x.Name);
}

Check if user control is already open

Im using WinForm C#
Have MainForm there is one panel where. my Inventory and Sell user controls are opening in panel. panel1.Controls.Add(inventory);
How to check if userControls are open?
When i check it i want to add tabControl. But i dont know how to add in tabPage controls without closing user control. Thanks
I mean if user control is already added in panel1.Controls. If its added gave name of user control
– Acid
How could the user control possibly be added to panel1.Controls without you knowing it? And if you added it yourself, you should already know the name of the user control.
Thus, all you have to do is loop through the controls in panel1.Controls and see if you find your user control. For example:
foreach (Control ctrl in panel1.Controls)
{
if (ctrl.Name == myUserControl)
{
// Found the control!
// (do something here...)
}
}
Alternatively, if you for whatever reason don't know the name of the control, you could still find all the controls of type UserControl that have been added to the panel's Controls collection. Like so:
foreach (Control ctrl in panel1.Controls)
{
if (ctrl is UserControl)
{
// Found a UserControl!
// (do something here...)
}
}
Remember that the Tag property provided on every control gives you a way to uniquely identify it. You can check that property for matches, too, if you don't know the name.
Not sure what you mean by open, but you can handle the ControlAdded event on the Panel class to capture when a control is added...
panel1.ControlAdded += new ControlEventHandler(p_ControlAdded);

foreach (Control ctrl in Frm.Controls) in which order it takes controls

I am having a peculiar problem with the order in which TextBox controls are added in to the form's Controls property.
Currently, I have the function:
public static bool IsValidate(System.Windows.Forms.Form Frm)
{
foreach (Control ctrl in Frm.Controls)
if (ctrl is TextBox)
// if (((TextBox)ctrl).AccessibleDescription == "Valid" && ((TextBox)ctrl).Text == string.Empty)
if (((TextBox)ctrl).AccessibleDescription == "Valid" && ((TextBox)ctrl).Text.Trim()== "")
{
MessageBox.Show(((TextBox)ctrl).AccessibleName + " Can't be Blank", Program.companyName, MessageBoxButtons.OK, MessageBoxIcon.Stop);
((TextBox)ctrl).Focus();
return false;
}
return true;
}
But it's iterating through the textboxes randomly, even though I have set their tab indices.
So I develop the same form again and create the textboxes sequentially. But still, when I pass the form to this function, it's iterating through the textboxes randomly.
I want to know if there is any property of the controls that would allow me to manage their flow.
You can do its easily.
Please use following syntax and which sort controls as per your tabindex in your form
foreach (Control control in this.Controls.Cast<Control>()
.OrderBy(c => c.TabIndex))
{
}
It's much easier to sort controls manually than manage their order in Controls collection. Example (sorts by TabOrder):
private static int CompareTabIndex(TextBox c1, TextBox c2)
{
return c1.TabIndex.CompareTo(c2.TabIndex);
}
public static bool IsValid(Form form)
{
List<TextBox> textBoxes = new List<TextBox>();
foreach(Control ctl in form.Controls)
{
TextBox textBox = ctl as TextBox;
if(textBox != null) textBoxes.Add(textBox);
}
textBoxes.Sort(new Comparison<TextBox>(CompareTabIndex));
foreach(TextBox textBox in textBoxes)
{
if(textBox.AccessibleDescription == "Valid" && textBox.Text.Trim() == "")
{
MessageBox.Show(textBox.AccessibleName + " Can't be Blank",
Program.companyName, MessageBoxButtons.OK, MessageBoxIcon.Stop);
textBox.Focus();
return false;
}
}
return true;
}
Is it really iterating over the controls "randomly"? (Implying that it is non-deterministic and the order is likely to change each time.) Or is it iterating over the controls in the same order each time, but not the order you expect? I suspect it's the latter, given that the C# language specification explicitly states the ordering of foreach (see first answer).
The tab order certainly won't affect the ordering of the controls. That's just for UI purposes. The actual order of the controls as array elements in the backing store is more likely controlled by the order in which they were created when building the form.
Can you elaborate more on that last part where you develop the form again "and take the text box sequentially"?
The controls are placed in order of the Z-order of the controls in the same parent container (top-most to bottom-most). To test try placing controls on a form and get the order. Apply "Send to Back" or "Bring to Front" for a few controls (at design time or runtime). The order of the foreach will change with the topmost control first and downwards.
The generated Designer code adds the controls based on the z-order. Lowest control first (top most control last). Hence it seems like it is based on the order in which it is added to the container.
I'm not sure if the implementation of BringToFront() and SendToBack() internally removes and adds controls in the required order. To me it makes sense to have it based on the z-order. And like mentioned above, we can always use our own ordering if required.
You can drop the controls into the form in the designer visually, and then open up the Form.Designer.cs source file and locate where the designer has typed in the code to add the controls to the Controls collection (i.e. the Controls.Add lines) and re-order those lines in the *.Designer.cs by hand. Once you've done that, the designer should leave your changes alone. I noticed that the designer writes them in reverse order. Your foreach should find them in the order that you arranged them.
i had this problem and i changed the order control name on Designer.cs ,
this.groupBox3.Controls.Add(this.txtPrice);
this.groupBox3.Controls.Add(this.txtDate);
See the Document Outline of the Form in view -> Other Windows -> Document Outline.
And then change the hierarchy of the controls as you need. the foreach looks there

System.Windows.Forms.Panel.Enabled = false color overload?

i have a System.Windows.Forms.Panel control in a windows application that has many labels and textboxes within the panel. When you call the Panel.Enabled = false command all of the textboxes and labels go gray and become un-editable which is the desired effect. Is there a way to overload the light gray colors when the panel is disabled?
Solution used:
Since the disabled color cant be overiden when disabled the following was used to disable only text boxes and labels on the Panel rather than the blanked Panel.Enabled = false;.
//Loop through the Member info Panel and find all the group boxes
foreach (Control cItem in Panel.Controls)
{
//A group box is found
if (cItem is GroupBox)
{
//Loop through all the group box components
foreach (Control cSubItem in cItem.Controls)
{
//If its a label of text box disable it
if (cSubItem is TextBox || cSubItem is Label)
{
cSubItem.Enabled = false;
}
}
}
}
There is no way to do a blanket override of how each Label and TextBox are Colored when they are disabled. But you can override each individual control after the containing panel is disabled and set them to the appropriate color.
The TextBox class (and more specifically the TextBoxBase class) will prefer an explicit color over the default Gray color for painting when disabled.
I wrote a blog post awhile back on how to achieve this effect: http://blogs.msdn.com/jaredpar/archive/2007/02/12/readonly-textbox-that-doesn-t-look-funny.aspx
As an alternative:
If the controls you wish to have a different enabled/disabled color you could iterate through the controls registered with the panel and assign their EnabledChanged event a custom function to change their color (based on type I assume). You'd probably want to filter the type of control you modify with this but you could use this to achieve your goal I believe.
Update:
Try this:
public void deselected(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
//TODO:check type of control and change background color
}
}
That will need to be placed inside your Form class but then you can use it on a event. Hope that helps.

Categories