tags:

views:

152

answers:

8

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,

+5  A: 

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);
}
Yakimych
better:int itemCount = ListView1.Items.Count;for (int i = itemCount - 1; i >= 0; i--){ var item = ListView1.Items[i]; ListView1.Items.Remove(item); ListView21.Items.Insert(0, item);}
Mark
+13  A: 

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.

Yossarian
Perhaps a bit nitpicking, but `ListView`'s `Items` does not have a `ToArray` method by itself.
Abel
Thanks, the first one can't work because there is no ToArrayI'll try the second one
Mark
It will work if you add a reference to LINQ, add a using-statement `using System.Linq` and (only if) you use .NET 3.5 or higher.
Abel
You can just add `Cast<ListViewItem>()` before `ToArray()` to get a generic `IEnumerable<T>` wrapping the `IEnumerable`.
Daniel Brückner
My last edit covers situation, when first suggestion works. (.net 3.5, linq)
Yossarian
A: 

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

Holli
A: 

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);
}
SiN
Because Items is a collection, it will fix the index of items in the listview. Remove(0), shift all to begin, remove(1) will then remove item 3(original index of 2, now 1).
PoweRoy
To fix this iterate over the collection from the last to the first item and it will work. `for (int i = ListView1.Items.Count - 1; i >= 0; i--)`. Further you have to insert at index zero instead of adding to the end to keep the correct order.
Daniel Brückner
+2  A: 

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.

Incognito
A: 

This looks like the WinForms list view control, so:

ListViewItem[] items = ListView1.Items.ToArray();
ListView1.Items.Clear();
ListView21.Items.AddRange(items);
Tim Robinson
A: 

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

zerkms
A: 

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?

Abel