C# removing items from listbox

Viewed 114971

I have a listbox being populated from a SQLDATA pull, and it pulls down some columns that i dont want like OBJECT_dfj, OBJECT_daskd. The key is all of these being with OBJECT_, is there a way to remove these from the listbox? I cannot change my SQL statement.

i tried this:

 foreach (string item in listBox1.Items)
 {
     string removelistitem = "OBJECT";
     if(item.Contains(removelistitem))
     {
         listBox1.Items.Remove(item);
     }
 }

but it gave me the error:

List that this enumerator is bound to has been modified. An enumerator can only be used if the list does not change.

16 Answers

You can't use an enumerator, you have to loop using an index, starting at the last item:

for (int n = listBox1.Items.Count - 1; n >= 0; --n)
{
    string removelistitem = "OBJECT";
    if (listBox1.Items[n].ToString().Contains(removelistitem))
    {
        listBox1.Items.RemoveAt(n);
    }
}

You can't modify the references in an enumerator whilst you enumerate over it; you must keep track of the ones to remove then remove them.

This is an example of the work around:

List<string> listbox = new List<string>();
List<object> toRemove = new List<object>();

foreach (string item in listbox)
{
    string removelistitem = "OBJECT";
    if (item.Contains(removelistitem))
    {
        toRemove.Add(item);
    }
}

foreach (string item in toRemove)
{
    listbox.Remove(item);
}

But if you're using c#3.5, you could say something like this.

listbox.Items = listbox.Items.Select(n => !n.Contains("OBJECT"));

You want to iterate backwards through using a counter instead of foreach. If you iterate forwards you have to adjust the counter as you delete items.

for(int i=listBox1.Items.Count - 1; i > -1; i--) {
{
    if(listBox1.Items[i].Contains("OBJECT"))
    {
        listBox1.Items.RemoveAt(i);
    }
}

The error you are getting means that

foreach (string item in listBox1.Items)

should be replaced with

for(int i = 0; i < listBox1.Items.Count; i++) {
    string item = (string)listBox1.Items[i];

In other words, don't use a foreach.

EDIT: Added cast to string in code above

EDIT2: Since you are using RemoveAt(), remember that your index for the next iteration (variable i in the example above) should not increment (since you just deleted it).

You can't modify a collection while you're iterating over it with foreach. You might try using a regular for() statement.

You may need to iterate backwards from the end of the collection to make sure you cover every item in the collection and don't accidentally overrun the end of the collection after removing an item (since the length would change). I can't remember if .NET accounts for that possibility or not.

The problem here is that you're changing your enumerator as you remove items from the list. This isn't valid with a 'foreach' loop. But just about any other type of loop will be OK.

So you could try something like this:

for(int i=0; i < listBox1.Items.Count; )
{
    string removelistitem = "OBJECT";
    if(listBox1.Items[i].Contains(removelistitem))
         listBox1.Items.Remove(item);
    else
        ++i;
}

You could try this method:

List<string> temp = new List<string>();

    foreach (string item in listBox1.Items)
    {
        string removelistitem = "OBJECT";
        if(item.Contains(removelistitem))
        {
            temp.Items.Add(item);
         }
     }

    foreach(string item in temp)
    {
       listBox1.Items.Remove(item);
    }

This should be correct as it simply copies the contents to a temporary list which is then used to delete it from the ListBox.

Everyone else please feel free to mention corrections as i'm not 100% sure it's completely correct, i used it a long time ago.

Sorry guys i had to adjust the string

sqldatapull = dr[0].ToString();
                if (sqldatapull.StartsWith("OBJECT"))
                {
                    sqldatapull = "";
                }
                listBox1.Items.Add(sqldatapull);
                for (int i = listBox1.Items.Count - 1; i >= 0; i--)
                {
                    if (String.IsNullOrEmpty(listBox1.Items[i] as String))
                        listBox1.Items.RemoveAt(i);
                }
            }

Your question implies that you're willing to modify other parts of the code, even though you can't modify the SQL Statement itself. Instead of removing them from the ListBox Collection, it might be easier to just exclude them in the first place. This code assumes you're connecting to SQL Server:

void PopulateListBox(ListBox listToPopulate)
{
    SqlConnection conn = new SqlConnection("myConnectionString"); 
    SqlCommand cmd = new SqlCommand("spMyStoredProc", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlDataReader reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        string item = reader.GetString(0); //or whatever column is displayed in the list
        if (!item.Contains("OBJECT_"))
            listToPopulate.Items.Add(item); 
    }
}

But if you're absolutely determined to do it this way you should check out this question on modifying an enumerable collection while iterating through it.

   for (int i = 0; i < listBox1.Items.Count; i++)
    {
        if (textBox1.Text == listBox1.Items[i].ToString())
        {
            jeElement = true;
            break;
        }
    }
    if (jeElement)
    {
        label1.Text = "je element";
    }
    else
    {
        label1.Text = "ni element";
    }
    textBox1.ResetText();
    textBox1.Focus();

}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt == true && e.KeyCode == Keys.A)
    {
        buttonCheck.PerformClick();
    }
}

}

Related