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);
}
}
Related
I have a function which clears all Comboboxes on the form and then try to update the text.
The new text is only shown if no Items are in the Item list.
Does anyone have an idea whats wrong?
I deleted all functions from the project so that only the necessary part is available.
https://www.dropbox.com/s/ibst7enrteyk9jb/Digitales_Auftragsformular.zip?dl=0
The project is attached. Simply start, go to tab "Werkzeuganfrage" there are two Comboboxes in red. One without Items = working, one with Items which is not working.
public Oberflaeche()
{
InitializeComponent();
List<ComboBox> myComboBoxes = GetControlsByType<ComboBox>(this, typeof(ComboBox));
foreach (ComboBox txt in myComboBoxes)
{
//txt.Text = "";
txt.SelectedIndex = -1;
}
Werkzeuganfrage_Combobox_rhino1_1.Text = "Rhino1_1";
Werkzeuganfrage_Combobox_rhino1_2.Text = "Rhino1_2";
comboBox1.Text = "Rhino1_1";
comboBox2.Text = "Rhino1_2";
}
public List<T> GetControlsByType<T>(Control container, Type type)
{
List<T> result = new List<T>();
foreach (Control c in container.Controls)
{
if (c.GetType() == type)
{
result.Add((T)Convert.ChangeType(c, typeof(T)));
}
if (c.HasChildren)
{
result.AddRange(GetControlsByType<T>(c, type));
}
}
return result;
}
I have seen lots of examples in this Question, but till not concluded. and i tried with all these EXAMPLES. I am trying to remove empty check box list which are binding from data base.
DataSet ds4 = getCheckBox(ViewState["id"].ToString());
chkEnvironment.DataSource = ds4;
chkEnvironment.DataTextField = "Environment";
chkEnvironment.DataValueField = "Environmentid";
chkEnvironment.DataBind();
But it is showing empty check boxes in my page. how to do it
protected void chkEnvironment_DataBound(object sender, EventArgs e)
{
foreach (ListItem item in chkEnvironment.Items)
{
if (item.Value == "NULL")
{
chkEnvironment.Items.Remove(item);
}
}
}
You cannot modify a collection during enumeration. You could store the items you want to remove later:
var itemsToRemove = new List<ListItem>();
foreach (ListItem item in chkEnvironment.Items)
{
if (item.Value == "NULL")
{
itemsToRemove.Add(item);
}
}
foreach(var item in itemsToRemove)
chkEnvironment.Items.Remove(item);
the same with LINQ:
var itemsToRemove = chkEnvironment.Items.Cast<ListItem>()
.Where(i => i.Value == "NULL")
.ToList();
foreach(var item in itemsToRemove)
chkEnvironment.Items.Remove(item);
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
}
}
I am unable to transfer the Selected Items from one ListBox to another ListBox:
protected void Button2_Click(object sender, EventArgs e)
{
foreach (ListItem li in ListBox2.Items)
{
if (li.Selected)
{
ListItem liNew = new ListItem(li.Text, li.Value);
ListBox1.Items.Add(liNew);
ListBox2.Items.Remove(liNew);
}
}
}
I am getting the exception:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
The problem is that you can't remove elements from a collection while you're iterating it. Instead, you can select the items that are selected :) and loop over them.
foreach(ListItem li in ListBox2.Items.Where(x => x.Selected)) {
ListItem liNew = new ListItem(li.Text, li.Value);
ListBox1.Items.Add(liNew);
ListBox2.Items.Remove(li);
}
(Also, I think you meant li, not liNew.)
Without LINQ, it might look like:
List<ListItem> toRemove = new List<ListItem>();
foreach(ListItem li in ListBox2.Items) {
if(li.Selected) {
ListItem liNew = new ListItem(li.Text, li.Value);
ListBox1.Items.Add(liNew);
toRemove.Add(li);
}
}
foreach(ListItem li in toRemove) {
ListBox2.Items.Remove(li);
}
Also, you can use a for loop, as suggested by #Steve:
for(int i = ListBox2.Items.Count; --i >= 0;) {
ListItem li = ListBox2.Items[i];
if(li.Selected) {
ListItem liNew = new ListItem(li.Text, li.Value);
ListBox1.Items.Add(liNew);
ListBox2.Items.RemoveAt(i);
}
}
I need a way to reorder this DropDownList so that...
ListItem lioak = new ListItem("Oak Pre-finished", "pre-finished oak");
...will show first.
foreach (DataRow r in ds.Tables[0].Rows)
{
if (r[0].ToString().ToLower() == "oak")
{
ListItem lioak = new ListItem("Oak Pre-finished", "pre-finished oak");
dd1Finish.Items.Add(lioak);
}
if (r[0].ToString().ToLower() == "white")
{
ListItem lioak = new ListItem("White pre-finished", "white");
dd2Finish.Items.Add(lioak);
}
if (r[1].ToString().ToLower() == "unfinished")
{
ListItem lioak = new ListItem("Oak Unfinished", "unfinished");
dd3Finish.Items.Add(lioak);
}
}
Thanks for any help in advance.
If you just want the "Oak Pre-finished" item at the start of the list you could try Insert -
ListItem lioak = new ListItem("Oak Pre-finished", "pre-finished oak");
dd1Finish.Items.Insert(0,lioak);