17

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.

egrunin
  • 24,650
  • 8
  • 50
  • 93
  • How is it being populated, via code or databinding? Is this WPF? WinForms? ASP.NET? – keithwarren7 Jan 19 '10 at 19:41
  • Winform, and its being populated from a SQLCOMMAND –  Jan 19 '10 at 19:43
  • This doesn't make any sense. The WinForms ListBox can only hold one column of text unless you're doing custom drawing. Are you concatenating the contents of all the fields, or what? – Ryan Lundy Jan 19 '10 at 19:49
  • What yes this is more then possible... i've done it tons of times. Hwo do i simply remove what i need to remove from the listbox. –  Jan 19 '10 at 19:52
  • When you say it pulls down "columns" you don't want, what you appear to mean is that you're ending up with items in your ListBox that you don't want. You're not displaying them as columns, but as a list. – Ryan Lundy Jan 19 '10 at 21:13
  • @Kyralessa: yes, he's saying "columns" when he means "rows" – egrunin Jan 19 '10 at 22:27
  • possible duplicate of [How do I do I loop through items in a list box and then remove that item?](http://stackoverflow.com/questions/380451/how-do-i-do-i-loop-through-items-in-a-list-box-and-then-remove-that-item) – nawfal Jun 05 '13 at 14:08

16 Answers16

22

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);
    }
}
egrunin
  • 24,650
  • 8
  • 50
  • 93
5

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"));
gingerbreadboy
  • 7,386
  • 5
  • 36
  • 62
3

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);
    }
}
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
1

You can do it in 1 line, by using Linq

listBox1.Cast<ListItem>().Where(p=>p.Text.Contains("OBJECT")).ToList().ForEach(listBox1.Items.Remove);
HGMamaci
  • 1,339
  • 12
  • 20
0

You can try this also, if you don't want to deal with the enumerator:

object ItemToDelete = null;
foreach (object lsbItem in listbox1.Items)
{
   if (lsbItem.ToString() == "-ITEM-")
   {
      ItemToDelete = lsbItem;                                  
   }
}

if (ItemToDelete != null)
    listbox1.Items.Remove(ItemToDelete);
Somebody
  • 2,667
  • 14
  • 60
  • 100
0

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).

Gabriel Magana
  • 4,338
  • 24
  • 23
  • its giving me : Error 1 Cannot implicitly convert type 'object' to 'string'. An explicit conversion exists (are you missing a cast?) –  Jan 19 '10 at 20:12
  • try string item = (string)listBox1.Items[i]; – Gabriel Magana Jan 19 '10 at 20:23
  • This won't work - he's removing items, so after items[5] is removed, items[6] will not point to the next item in the original list. Instead, you have to iterate from the end to the beginning. – egrunin Apr 01 '15 at 05:31
  • @egrugin, that's EXACTLY what I said in my "edit2" comment. Iterating backwards is just another way to address the issue. – Gabriel Magana Apr 05 '15 at 17:41
0

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.

David
  • 5,651
  • 2
  • 16
  • 4
0

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;
}
Sam Holloway
  • 1,999
  • 15
  • 14
  • Error 1 'object' does not contain a definition for 'Contains' and no extension method 'Contains' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?) –  Jan 19 '10 at 20:08
0

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.

Jamie Keeling
  • 9,806
  • 17
  • 65
  • 102
0

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);
                }
            }
0

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.

Community
  • 1
  • 1
Jeremy S
  • 1,043
  • 1
  • 7
  • 9
0

With this code you can remove every item from your listbox ... Notice that you should write this code in the click event of your button :

        if (listBox1.SelectedIndex != -1)
        {
            listBox1.Items.RemoveAt(listBox1.SelectedIndex);
        } 
MOKp
  • 21
  • 2
0

I found out the hard way that if your listbox items are assigned via a data source

List<String> workTables = hhsdbutils.GetWorkTableNames();
listBoxWork.DataSource = workTables;

...you have to unbind that before doing the removal:

listBoxWork.DataSource = null;
for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
{
    if (listBoxWork.Items[i].ToString().Contains(listboxVal))
    {
        listBoxWork.Items.RemoveAt(i);
    }
}

Without the "listBoxWork.DataSource = null;" line, I was getting, "Value does not fall within the expected range"

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
0
protected void lbAddtoDestination_Click(object sender, EventArgs e)
        {
            AddRemoveItemsListBox(lstSourceSkills, lstDestinationSkills);
        }
        protected void lbRemovefromDestination_Click(object sender, EventArgs e)
        {
            AddRemoveItemsListBox(lstDestinationSkills, lstSourceSkills);
        }
        private void AddRemoveItemsListBox(ListBox source, ListBox destination)
        {
            List<ListItem> toBeRemoved = new List<ListItem>();
            foreach (ListItem item in source.Items)
            {
                if (item.Selected)
                {
                    toBeRemoved.Add(item);
                    destination.Items.Add(item);
                }
            }
            foreach (ListItem item in toBeRemoved) source.Items.Remove(item);
        }
codingEnthusiast
  • 3,800
  • 2
  • 25
  • 37
0

You can use following code too:

 foreach (var item in listBox1.Items.Cast<string>().ToList())
 {
     string removelistitem = "OBJECT";
     if (item.Contains(removelistitem))
     {
        listBox1.Items.Remove(item);
     }
 }
Masoud
  • 8,020
  • 12
  • 62
  • 123
0
   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();
    }
}

}

122
  • 1
  • 1