Mark
Mark

Reputation: 33

Foreach doesn't go through all items?

I have this code:

       foreach (var item in ListView1.Items)
            {
                ListView1.Items.Remove(item);
                ListView21.Items.Add(item);
            }

the loop stops at half of the items?

Any idea?

EDIT

Well, maybe it's my mistake, I need to clarify that this is UltraListView control from Infrajistics, where I can't add item to another list unless I remove it or clone it from the original list.

But thanks, most of the comments regarding do not modify the list within the loop were correct, so this code works:

           foreach (var item in listView1.Items)
            {
                var i = item.Clone(true);
                listView2.Items.Add(i);
            }
            listView1.Items.Clear();

Thanks,

Upvotes: 3

Views: 3044

Answers (8)

Abel
Abel

Reputation: 57149

You are looping through all items, removing all of them, then adding them to another list. As others have commented, you cannot remove items from a list in a for-each. Why not looping through all items to add them to your other list, and then remove them all in one go?

foreach (var item in ListView1.Items)
{
    ListView21.Items.Add(item);
}
ListView1.Items.Clear();   // remove all

PS: is this an ASP.NET listview or a WinForms listview?

Upvotes: 0

nothrow
nothrow

Reputation: 16168

You cannot modify iterated collection, it should die with exception (or in undefined behavior). Try making a copy of the array:

   foreach (var item in ListView1.Items.ToArray())
   {
       ListView1.Items.Remove(item);
       ListView21.Items.Add(item);
   }

EDIT:

in fact, your example code can be achieved by writing:

ListView21.Items.AddRange(ListView1.Items);
ListView1.Items.Clear();

(which in fact isn't EXACTLY what you are doing, but gives the same result and I think it won't bother you having the same content in both listviews for a moment). The latter is supported since .NET2.0, first solution requires linq, and therefore .NET3.5.

Upvotes: 15

Yakimych
Yakimych

Reputation: 17752

You are modifying the collection you are looping through. Try using a for statement from top to bottom (from the item with the highest index to 0).

for (int i = ListView1.Items.Count - 1; i >= 0; i--)
{
    var item = ListView1.Items[i];
    ListView1.Items.Remove(item);
    ListView21.Items.Insert(0, item);
}

Upvotes: 9

zerkms
zerkms

Reputation: 254886

Why just not CopyTo() to new list and then Clear() items?

Upvotes: 0

Tim Robinson
Tim Robinson

Reputation: 54724

This looks like the WinForms list view control, so:

ListViewItem[] items = ListView1.Items.ToArray();
ListView1.Items.Clear();
ListView21.Items.AddRange(items);

Upvotes: 0

Incognito
Incognito

Reputation: 16577

It will cause a runtime exception, complaining that you cannot modify the collection while iterating through it. You have to use for loop instead.

for(int index = Items.Count; index > 0; index--)
{
    .......
    // use Add and RemoveAt
}

EDIT : As mentioned by others. If you just need to move items from one collection to the other. AddRange and Clear will be better.

Upvotes: 2

SiN
SiN

Reputation: 3754

That's because you're changing the collection inside the loop. Use a normal for loop as follows:

for(int i=0; i < ListView1.Items.Count-1; i++)
{
       ListView21.Items.Add(ListView1.Items[i]);
       ListView1.Items.RemoveAt(i);
}

Upvotes: -1

TalkingCode
TalkingCode

Reputation: 13557

Do you get any exception or error message? Looping in a collection and remove items from the same collection is always a bad idea.

Upvotes: 0

Related Questions