By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,183 Members | 1,190 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,183 IT Pros & Developers. It's quick & easy.

Weird problem with listview and collection

P: n/a
I have a listview control and a collection object right now that I'm trying
to pass information to and from. Whenever I click on the checkbox, I want
it to remove certain listview items and add them to the collection.
Whenever I uncheck the checkbox, I want to add the items back into the
listview from the collection, and remove them from the collection so I can
do the process multiple times. The listview tag is being used as a key, so
I know which item to remove. It seems that it adds 29 items to the
collection, but then when I go to add them back to the listview, it only
adds 10. What am I doing wrong here?

Dim tmpItem As ListViewItem

If chkOnlyExternal.Checked = True Then

'Remove internal users.

For Each lvitem As ListViewItem In lstUsers.Items

If db.IsInternalUser(lvitem.Tag.ToString) Then

tmpItem = lvitem

lvCollection.Add(lvitem, lvItem.Tag.ToString)

lvitem.Remove()

rmCount += 1

End If

Next

MessageBox.Show("Removed from listview: " & rmCount.ToString)

Else

MessageBox.Show("Collection count: " & lvCollection.Count.ToString)

If lvCollection.Count > 0 Then

For Each lvItem As ListViewItem In lvCollection

lstUsers.Items.Add(lvItem)

lvCollection.Remove(lvItem.Tag.ToString)

addCount += 1

Next

MessageBox.Show("Added back to listview: " & addCount.ToString)

End If

End If


Nov 21 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
This is a common mistake/mis-conception.
You should not modify a collection while iterating through it.
In fact, some collection implementations will raise an error if you attempt
to alter (add or remove) the contents while enumerating over it.

Here is what is happening...
Say you have a collection with 5 items.
You are iterating through it, and you are on item 2, so your enumeration
pointer is at 2.
You remove the current item.
There are now 4 items in the collection.
Your enumeration pointer is still at 2, but old item 2 is gone, your current
item should be old item 3.
You move to the next item 3, but that really steps to old item 4.
Same thing would happen if you dynamically resized an array while stepping
through it.

Make sense?
So if you step through a collection, removing the current item, you end up
only getting every other item.

There are numerous ways to get around this.
If you are using keys, then you could step through the collection adding
each item to the other. But keep track of which items were moved. Then after
you have finished with the collection, go back and remove the ones you moved
by key. If you are moving everything, then you could just empty the
collection.

Treat the collection like an array and use indexes (For index) instead of
For Each, and step backwards through the collection. Instead of going from
beginning to end, which causes thing to move up when removed, go from end to
beginning.

There are other ways to deal with this as well, but stepping backward I
believe might be the most common.

Gerald

"Matt Michael" <ih***@spamforme.com> wrote in message
news:eM**************@TK2MSFTNGP15.phx.gbl...
I have a listview control and a collection object right now that I'm trying to pass information to and from. Whenever I click on the checkbox, I want
it to remove certain listview items and add them to the collection.
Whenever I uncheck the checkbox, I want to add the items back into the
listview from the collection, and remove them from the collection so I can
do the process multiple times. The listview tag is being used as a key, so I know which item to remove. It seems that it adds 29 items to the
collection, but then when I go to add them back to the listview, it only
adds 10. What am I doing wrong here?

Dim tmpItem As ListViewItem

If chkOnlyExternal.Checked = True Then

'Remove internal users.

For Each lvitem As ListViewItem In lstUsers.Items

If db.IsInternalUser(lvitem.Tag.ToString) Then

tmpItem = lvitem

lvCollection.Add(lvitem, lvItem.Tag.ToString)

lvitem.Remove()

rmCount += 1

End If

Next

MessageBox.Show("Removed from listview: " & rmCount.ToString)

Else

MessageBox.Show("Collection count: " & lvCollection.Count.ToString)

If lvCollection.Count > 0 Then

For Each lvItem As ListViewItem In lvCollection

lstUsers.Items.Add(lvItem)

lvCollection.Remove(lvItem.Tag.ToString)

addCount += 1

Next

MessageBox.Show("Added back to listview: " & addCount.ToString)

End If

End If

Nov 21 '05 #2

P: n/a
Gerald,

Thanks for responding, I see now where I made my error. I'm clearing the
collection every time now, and everything is working just fine for me.
Thanks a lot, this would have bothered me all afternoon!

-Matt
"Gerald Hernandez" <Cablewizard@sp*********@Yahoo.com> wrote in message
news:ev**************@tk2msftngp13.phx.gbl...
This is a common mistake/mis-conception.
You should not modify a collection while iterating through it.
In fact, some collection implementations will raise an error if you
attempt
to alter (add or remove) the contents while enumerating over it.

Here is what is happening...
Say you have a collection with 5 items.
You are iterating through it, and you are on item 2, so your enumeration
pointer is at 2.
You remove the current item.
There are now 4 items in the collection.
Your enumeration pointer is still at 2, but old item 2 is gone, your
current
item should be old item 3.
You move to the next item 3, but that really steps to old item 4.
Same thing would happen if you dynamically resized an array while stepping
through it.

Make sense?
So if you step through a collection, removing the current item, you end up
only getting every other item.

There are numerous ways to get around this.
If you are using keys, then you could step through the collection adding
each item to the other. But keep track of which items were moved. Then
after
you have finished with the collection, go back and remove the ones you
moved
by key. If you are moving everything, then you could just empty the
collection.

Treat the collection like an array and use indexes (For index) instead of
For Each, and step backwards through the collection. Instead of going from
beginning to end, which causes thing to move up when removed, go from end
to
beginning.

There are other ways to deal with this as well, but stepping backward I
believe might be the most common.

Gerald

"Matt Michael" <ih***@spamforme.com> wrote in message
news:eM**************@TK2MSFTNGP15.phx.gbl...
I have a listview control and a collection object right now that I'm

trying
to pass information to and from. Whenever I click on the checkbox, I
want
it to remove certain listview items and add them to the collection.
Whenever I uncheck the checkbox, I want to add the items back into the
listview from the collection, and remove them from the collection so I
can
do the process multiple times. The listview tag is being used as a key,

so
I know which item to remove. It seems that it adds 29 items to the
collection, but then when I go to add them back to the listview, it only
adds 10. What am I doing wrong here?

Dim tmpItem As ListViewItem

If chkOnlyExternal.Checked = True Then

'Remove internal users.

For Each lvitem As ListViewItem In lstUsers.Items

If db.IsInternalUser(lvitem.Tag.ToString) Then

tmpItem = lvitem

lvCollection.Add(lvitem, lvItem.Tag.ToString)

lvitem.Remove()

rmCount += 1

End If

Next

MessageBox.Show("Removed from listview: " & rmCount.ToString)

Else

MessageBox.Show("Collection count: " & lvCollection.Count.ToString)

If lvCollection.Count > 0 Then

For Each lvItem As ListViewItem In lvCollection

lstUsers.Items.Add(lvItem)

lvCollection.Remove(lvItem.Tag.ToString)

addCount += 1

Next

MessageBox.Show("Added back to listview: " & addCount.ToString)

End If

End If


Nov 21 '05 #3

P: n/a
psh... you kids these days at Reschini and your crazy ideas :P
"Matt Michael" <ih***@spamforme.com> wrote in message
news:eM**************@TK2MSFTNGP15.phx.gbl...
I have a listview control and a collection object right now that I'm trying
to pass information to and from. Whenever I click on the checkbox, I want
it to remove certain listview items and add them to the collection.
Whenever I uncheck the checkbox, I want to add the items back into the
listview from the collection, and remove them from the collection so I can
do the process multiple times. The listview tag is being used as a key, so
I know which item to remove. It seems that it adds 29 items to the
collection, but then when I go to add them back to the listview, it only
adds 10. What am I doing wrong here?

Dim tmpItem As ListViewItem

If chkOnlyExternal.Checked = True Then

'Remove internal users.

For Each lvitem As ListViewItem In lstUsers.Items

If db.IsInternalUser(lvitem.Tag.ToString) Then

tmpItem = lvitem

lvCollection.Add(lvitem, lvItem.Tag.ToString)

lvitem.Remove()

rmCount += 1

End If

Next

MessageBox.Show("Removed from listview: " & rmCount.ToString)

Else

MessageBox.Show("Collection count: " & lvCollection.Count.ToString)

If lvCollection.Count > 0 Then

For Each lvItem As ListViewItem In lvCollection

lstUsers.Items.Add(lvItem)

lvCollection.Remove(lvItem.Tag.ToString)

addCount += 1

Next

MessageBox.Show("Added back to listview: " & addCount.ToString)

End If

End If

Nov 21 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.