how to find controls in usercontrols and pass it to string builder - c#

i can iterate through the controls which are on panel by this two code
Form4 fl = new Form4();
StringBuilder sb = new StringBuilder();
foreach (Control c in panel1.Controls)
{
if (c is ComboBox)
{
ComboBox cb = (ComboBox)c;
sb.Append(cb.Text);
fl.comboBox1.Text = sb.ToString();
fl.Show();
}
}
OR by this
List lst = new List();
void GetComboBoxValues()
StringBuilder sb = new StringBuilder();
{
sb.Append(c.Text + "\r\n");
}
MessageBox.Show(sb.ToString());
}
but i add a panel and on panel a usercontrol which contains a combobox and textbox how that can be possible to find controls and add to the string builder
so i thought iterating through usercontrol and finding the text and adding it to the string builder,is that possible?

You can use this recursive method to find the controls
var combos = FindControls<ComboBox>(panel1).ToList();
or
var text = String.Join(Environment.NewLine,
FindControls<ComboBox>(this).Select(c => c.Text));
IEnumerable<T> FindControls<T>(Control ctrl) where T : Control
{
foreach (Control c in ctrl.Controls)
{
if (c.GetType() == typeof(T)) yield return (T)c;
foreach (var subC in FindControls<T>(c))
yield return subC;
}
}
-----------------EDIT------------------
can you suggest easiest method
List<ComboBox> combos = new List<ComboBox>();
FindComboBoxes(this,combos);
StringBuilder sb = new StringBuilder();
foreach (var combo in combos)
{
sb.AppendLine(combo.Text);
}
void FindComboBoxes(Control parent,List<ComboBox> fillThis)
{
foreach (Control c in parent.Controls)
{
if (c.GetType() == typeof(ComboBox)) fillThis.Add((ComboBox)c);
FindComboBoxes(c, fillThis);
}
}

Responding to the comment left for L.B's answer. Personally I believe L.B's answer is the easiest and requires the least amount of coding, the best thing is it will find all the controls of a specific type on a panel no matter how nested they are(imagine if you have a user control inside a user control).
Just copy the FindControls method from LB's answer to your solution as is and where you need to loop through the controls of the panel, do something like this:
StringBuilder sb = new StringBuilder();
var comboBoxes = FindControls<ComboBox>(panel1).ToList();
var textBoxes = FindControls<TextBox>(panel1).ToList();
foreach (var comboBox in comboBoxes)
sb.AppendLine(comboBox.SelectedItem.ToString());
foreach (var textbox in textBoxes)
sb.AppendLine(textbox.Text);
MessageBox.Show(sb.ToString());
A simple example would be something like this, but be warned that it will not work if you have a case of a user control inside a user control, so I would strongly suggest going with LB's example:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < panel1.Controls.Count; i++)
{
if (panel1.Controls[i].Controls.Count > 0)
{
//Iterate through the controls in the user control
foreach(Control c in panel1.Controls[i].Controls)
{
}
}
else
{
//Handle the controls with no children
}
}

Related

Retrieving drop down list items from list of controls

I am attempting to retrieve a ListItemCollection from a List of controls. This List contains many controls of different types - DropDownList, Label, TextBox.
I would like to retrieve all ListItem from all the DropDownList controls contained in the original List of controls.
My thought process so far has been to extract all of the DropDownList controls into a new list, and iterate though this to pull out each ListItem - however, every DropDownList control is coming up with 0 items
ControlCollection cList = pnlContent.Controls;
List<DropDownList> ddlList = new List<DropDownList>();
foreach (Control c in cList)
{
if (c.GetType() == new DropDownList().GetType())
{
ddlList.Add((DropDownList)c);
}
}
ListItemCollection itemCollection = new ListItemCollection();
foreach (DropDownList ddl in ddlList)
{
foreach(ListItem li in ddl.Items)
{
itemCollection.Add(li);
}
}
I'm sure this is the wrong (and massively inefficient) way of doing this. Any help would be appreciated.
This will do:
public IEnumerable<ListItem> GetListItems(ControlCollection controls)
{
return controls.OfType<DropDownList>().SelectMany(c => c.Items.OfType<ListItem>());
}
I currently do not have an installation where I can test this, but as a line of thought I would use Linq to do this.
Here is an example that you should be able to use;
var type = new DropDownList().GetType();
var listOfControl = from c in pnlContent.Controls
where c.GetType() == type
select ((DropDownList)c).Items;
Try this:
var ddlList = cList.OfType<DropDownList>();
ListItemCollection itemCollection = new ListItemCollection();
// option 1
var temp = ddlList.Select(ddl => ddl.Items.Cast<ListItem>()).SelectMany(li => li).ToArray();
itemCollection.AddRange(temp);
// or option 2
var temp = ddlList.Select(ddl => ddl.Items.Cast<ListItem>()).SelectMany(li => li);
foreach (var listItem in temp)
{
itemCollection.Add(listItem);
}
comboBox1.Items.Add(button1);
comboBox1.Items.Add(button2);
comboBox1.Items.Add(dateTimePicker1);
comboBox1.Items.Add(checkBox1);
comboBox2.Items.Add(button3);
comboBox2.Items.Add(button4);
comboBox2.Items.Add(dateTimePicker2);
comboBox2.Items.Add(checkBox2);
comboBox3.Items.Add(button5);
comboBox3.Items.Add(dateTimePicker3);
comboBox3.Items.Add(checkBox3);
comboBox3.Items.Add(checkBox4);
List<ComboBox> ddlList = new List<ComboBox>();
foreach (Control c in panel1.Controls)
{
if (c is ComboBox)
{
ddlList.Add((ComboBox)c);
}
}
List<Control> itemCollection = new List<Control>();
foreach (ComboBox ddl in ddlList)
{
foreach (var li in ddl.Items)
{
itemCollection.Add((Control)li);
}
}

"Unable to cast object" while looping through programatically created textboxes

I have some Textboxes that are created dynamically --
int i = 1;
while (reader.Read())
{
System.Web.UI.WebControls.TextBox textBox = new System.Web.UI.WebControls.TextBox();
textBox.ID = reader["field_id"].ToString();
textBox.Enabled = false;
HtmlGenericControl div = new HtmlGenericControl("div");
if(i%2 != 0)
div.Attributes.Add("style", "margin-right:120px;padding-bottom:20px;");
if (i % 2 == 0)
div.Attributes.Add("style", "padding-bottom:20px;");
div.Attributes.Add("class", "inline fourcol");
div.InnerHtml = "<label>" + reader["field"] + "</label>";
div.Controls.Add(textBox);
panelId.Controls.Add(div);
textBox.Text = reader["field_value"].ToString();
++i;
}
That works fine (at least i'm sure -they show up how they should). But when i try to loop through them to enable them, or get their values, i get an "Unable to cast object of type 'System.Web.UI.LiteralControl' to type 'System.Web.UI.WebControls.TextBox'. " error.
This is how i've been trying to do it --
public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
foreach (System.Web.UI.WebControls.TextBox t in panel.Controls)
{
t.Enabled = true;
}
}
Thanks!
You're looping over panel.Controls, which will loop over every control in the panel. This is not necessarily the same thing as looping over everything you've added. If there was something else inside the panel that existed when you started, you will end up getting that too.
What you probably wanted was this:
foreach (var t in panel.Controls.OfType<System.Web.UI.WebControls.TextBox>())
{
t.Enabled = true;
}
You are putting each textbox inside a "div" control which is HtmlGenericControl, then inside the panel control. So first you must search for the HtmlGenericControl inside panelId.Controls
A sample code that might help you:
public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
foreach (Control c in panelId.Controls)
{
if (c is HtmlGenericControl)
{
foreach (var textbox in c.Controls.OfType<TextBox>()) //ofType returns IEnumerable<TextBox>
textbox.Enabled = true;
}
}
}
There is a control inside your Panel, that is not a TextBox and could not be cast to it. You should place a breakpoint before the loop and check the panel.Control collection contents in debug mode.
You can avoid the issue if you don't specify a type in the foreach loop and do the safe cast yourself.
foreach (var t in panel.Controls)
{
var textbox = t as System.Web.UI.WebControls.TextBox;
if(textbox != null)
{
textbox.Enabled = true;
}
}
You should check if control is TextBox
public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
foreach (var t in panel.Controls)
{
if (t is System.Web.UI.WebControls.TextBox)
((System.Web.UI.WebControls.TextBox)t).Enabled = true;
}
}
The Controls collection will contain a collection of all the controls in the panel - not just TextBoxes. You can iterate through all of the controls and use the as operator to perform a type cast. If the type cast succeeds then you may enable the textbox.
public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
foreach (var control t in panel.Controls)
{
System.Web.UI.WebControls.TextBox textBox = control as System.Web.UI.WebControls.TextBox;
if (textBox != null)
{
control.Enabled = true;
}
}
}
you add the textbox to the div element and the div element to the panel. therefore you need to select the controls in the panel and then find the textbox.
foreach (var t in panel.Controls.Cast<Control>().SelectMany(c => c.Controls))
{
if (t is TextBox == false) continue;
((TextBox)t).Enabled = true;
}

Using a foreach loop to retrieve TextBox's within a GroupBox

I have ten group boxes in a WinForm. Each group box contains 10 text boxes, and I have defined each TextBox name. How can I get each text box using a foreach loop?
foreach(Control gb in this.Controls)
{
if(gb is GroupBox)
{
foreach(Control tb in gb.Controls)
{
if(tb is TextBox)
{
//here is where you access all the textboxs.
}
}
}
}
But if you have defined each TextBox name
What's the point to get each TextBox by a loop?
You could define a List<TextBox> to hold reference of each TextBox while creating them, then just go though the List to get access of each TextBox.
Here is my suggestion:
foreach(var groupBox in Controls.OfType<GroupBox>())
{
foreach(var textBox in groupBox.Controls.OfType<TextBox>())
{
// Do Something
}
}
Or having it in one loop:
foreach (var textBox in Controls.OfType<GroupBox>().SelectMany(groupBox => groupBox.Controls.OfType<TextBox>()))
{
// Do Something
}
try following code,
Control.ControlCollection coll = this.Controls;
foreach(Control c in coll) {
if(c != null)
}
foreach (var ctrl in gbDatabaseColumns.Controls)
{
if (ctrl is DevExpress.XtraEditors.TextEdit)
{
StoreTextEdit(config, (ctrl as DevExpress.XtraEditors.TextEdit));
}
}
foreach (Control txx in groupBox2.Controls)
{
if (txx is TextBox)
txx.Text = "";
if (txx is ComboBox)
txx.Text = "";
// if (txx is DateTimePicker)
// txx.Text = ""; Datetimepicker text can't be erased
}

how to get value of more than one text box in a loop

I have some text boxes in my page. I want to get all text box values in an array and insert in to table of database.
Is there any option to work by loop
public IEnumerable<string> AllTextsFromTextboxes()
{
foreach (var control in Page.Controls.OfType<TextBox>())
{
yield return control.Text;
}
}
you can try something on these lines, if all the textbox are on the page directly
foreach(Control c in Page.Controls)
{
if (c is TextBox)
{
//get the text
}
}
This will not work for child controls for that you will have to recursively iterate
yes, you can put your controls in panel and then iterate and get value. e.g.
foreach (Control ctrl in Panel1.Controls)
{
if (ctrl.GetType().Name == "TextBox")
{
if (((TextBox)ctrl).Text != string.Empty)
{
// do stuff here
}
}
}
private void FindSelecedControl(Control control)
{
if (control is TextBox)
{
TextBox txt = (TextBox)control;
txt.Enabled = false;
}
else
{
for (int i = 0; i < control.Controls.Count; i++)
{
FindSelecedControl(control.Controls[i]);
}
}
}
foreach (Control control1 in this.Form.Controls)
{
FindSelecedControl(control1);
}

Foreach Control in form, how can I do something to all the TextBoxes in my Form?

How can I use a Foreach Statement to do something to my TextBoxes?
foreach (Control X in this.Controls)
{
Check if the controls is a TextBox, if it is delete it's .Text letters.
}
If you are using C# 3.0 or higher you can do the following
foreach ( TextBox tb in this.Controls.OfType<TextBox>()) {
..
}
Without C# 3.0 you can do the following
foreach ( Control c in this.Controls ) {
TextBox tb = c as TextBox;
if ( null != tb ) {
...
}
}
Or even better, write OfType in C# 2.0.
public static IEnumerable<T> OfType<T>(IEnumerable e) where T : class {
foreach ( object cur in e ) {
T val = cur as T;
if ( val != null ) {
yield return val;
}
}
}
foreach ( TextBox tb in OfType<TextBox>(this.Controls)) {
..
}
You're looking for
foreach (Control x in this.Controls)
{
if (x is TextBox)
{
((TextBox)x).Text = String.Empty;
}
}
The trick here is that Controls is not a List<> or IEnumerable but a ControlCollection.
I recommend using an extension of Control that will return something more..queriyable ;)
public static IEnumerable<Control> All(this ControlCollection controls)
{
foreach (Control control in controls)
{
foreach (Control grandChild in control.Controls.All())
yield return grandChild;
yield return control;
}
}
Then you can do :
foreach(var textbox in this.Controls.All().OfType<TextBox>)
{
// Apply logic to the textbox here
}
Also you can use LINQ. For example for clear Textbox text do something like:
this.Controls.OfType<TextBox>().ToList().ForEach(t => t.Text = string.Empty);
foreach (Control X in this.Controls)
{
if (X is TextBox)
{
(X as TextBox).Text = string.Empty;
}
}
You can do the following:
foreach (Control X in this.Controls)
{
TextBox tb = X as TextBox;
if (tb != null)
{
string text = tb.Text;
// Do something to text...
tb.Text = string.Empty; // Clears it out...
}
}
A lot of the above work.
Just to add. If your textboxes are not directly on the form but are on other container objects like a GroupBox, you will have to get the GroupBox object and then iterate through the GroupBox to access the textboxes contained therein.
foreach(Control t in this.Controls.OfType<GroupBox>())
{
foreach (Control tt in t.Controls.OfType<TextBox>())
{
// do stuff
}
}
Just add other control types:
public static void ClearControls(Control c)
{
foreach (Control Ctrl in c.Controls)
{
//Console.WriteLine(Ctrl.GetType().ToString());
//MessageBox.Show ( (Ctrl.GetType().ToString())) ;
switch (Ctrl.GetType().ToString())
{
case "System.Windows.Forms.CheckBox":
((CheckBox)Ctrl).Checked = false;
break;
case "System.Windows.Forms.TextBox":
((TextBox)Ctrl).Text = "";
break;
case "System.Windows.Forms.RichTextBox":
((RichTextBox)Ctrl).Text = "";
break;
case "System.Windows.Forms.ComboBox":
((ComboBox)Ctrl).SelectedIndex = -1;
((ComboBox)Ctrl).SelectedIndex = -1;
break;
case "System.Windows.Forms.MaskedTextBox":
((MaskedTextBox)Ctrl).Text = "";
break;
case "Infragistics.Win.UltraWinMaskedEdit.UltraMaskedEdit":
((UltraMaskedEdit)Ctrl).Text = "";
break;
case "Infragistics.Win.UltraWinEditors.UltraDateTimeEditor":
DateTime dt = DateTime.Now;
string shortDate = dt.ToShortDateString();
((UltraDateTimeEditor)Ctrl).Text = shortDate;
break;
case "System.Windows.Forms.RichTextBox":
((RichTextBox)Ctrl).Text = "";
break;
case " Infragistics.Win.UltraWinGrid.UltraCombo":
((UltraCombo)Ctrl).Text = "";
break;
case "Infragistics.Win.UltraWinEditors.UltraCurrencyEditor":
((UltraCurrencyEditor)Ctrl).Value = 0.0m;
break;
default:
if (Ctrl.Controls.Count > 0)
ClearControls(Ctrl);
break;
}
}
}
foreach (Control x in this.Controls)
{
if (x is TextBox)
{
((TextBox)x).Text = String.Empty;
//instead of above line we can use
*** x.resetText();
}
}
Check this:
foreach (Control x in this.Controls)
{
if (x is TextBox)
{
x.Text = "";
}
}
simple using linq, change as you see fit for whatever control your dealing with.
private void DisableButtons()
{
foreach (var ctl in Controls.OfType<Button>())
{
ctl.Enabled = false;
}
}
private void EnableButtons()
{
foreach (var ctl in Controls.OfType<Button>())
{
ctl.Enabled = true;
}
}
Even better, you can encapsule this to clear any type of controls you want in one method, like this:
public static void EstadoControles<T>(object control, bool estado, bool limpiar = false) where T : Control
{
foreach (var textEdits in ((T)control).Controls.OfType<TextEdit>()) textEdits.Enabled = estado;
foreach (var textLookUpEdits in ((T)control).Controls.OfType<LookUpEdit>()) textLookUpEdits.Enabled = estado;
if (!limpiar) return;
{
foreach (var textEdits in ((T)control).Controls.OfType<TextEdit>()) textEdits.Text = string.Empty;
foreach (var textLookUpEdits in ((T)control).Controls.OfType<LookUpEdit>()) textLookUpEdits.EditValue = #"-1";
}
}
private IEnumerable<TextBox> GetTextBoxes(Control control)
{
if (control is TextBox textBox)
{
yield return textBox;
}
if (control.HasChildren)
{
foreach (Control ctr in control.Controls)
{
foreach (var textbox in GetTextBoxes(ctr))
{
yield return textbox;
}
}
}
}
I found this to work very well, but initially I have my textboxes on a panel so none of my textboxes cleared as expected so I added
this.panel1.Controls.....
Which got me to thinking that is you have lots of textboxes for different functions and only some need to be cleared out, perhaps using the multiple panel hierarchies you can target just a few and not all.
foreach ( TextBox tb in this.Controls.OfType<TextBox>()) {
..
}

Categories