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

ListViewItem.Remove() throws exception inside AfterLabelEdit

P: n/a
An interesting problem:
I have a ListView with LabelEdit set to TRUE. When I change the label, I
want to make some decisions as to whether the ListViewItem (that's just been
edited) should stay in the ListView or not.
The natural place to inspect this is in the AfterLabelEdit event...
If the decision is to take the item out, I used the ListViewItem.Remove().
However - check this out:
A) say that the item's index is N (indices are zero-based)
B) if there exists an item after it (i.e. with index N+1)
then this item gets quietly removed
C) if the item is the last in the list,an exception is thrown
saying that index N (requested to be removed) is non-existant.

It looks like:
D) when the item is being edited, it is taken OUT of the
ListView.Items collection. So - the original item N+1 moves up and
is temporarily assigned index N (that is how it gets removed - see
B) above)
E) if however, item N is the last in the collection and gets
temporarily taken out while being edited, then of course we get
and exception thrown as there isn't an item with index N

This can easily be proved:
1. create a new Windows Forms project
2. add a ListView to the form
3. Set LabelEdit to TRUE
4. Add 3 items to the list, with labels e.g. 'Item1', 'Item2' and 'Item3'
5. Create a handler for the AfterLabelEdit event
6. Inside this handler add this code:

ListViewItem item = listView1.Items[e.Item];
item.Remove();

7. Run the application
8. Edit the first item and press Enter -the second item is removed
9. Next, edit the last item then press Enter -exception is thrown

This is all very nice...

But - can someone suggest an elegant workaround , i.e. - where and
how can I remove items after they have been edited?

Many thanks in advance.
Jul 28 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Actually, what really happens is this:

1. You begin editing the first item (index 0), add characters and press
Enter
2. The AfterLabelEdit event fires for index 0. At this stage the change is
*not yet commited* to the actual item
3. You remove the item with index 0
4. Control returns to Windows that now tries to commit the change to index
0. Only problem is that you removed that item so it applies it to whatever
is at index 0 now, which happens to be your second item (i.e. the one that
previously had index 1). To you this looks like the second item is removed,
while in fact the first item is removed and the second item simply gets its
text changed

Imagine what happens when you edit the last item......
(btw, you can see that the correct item is being removed if you press Esc
instead of Enter)

To work around this use BeginInvoke to asynchronously invoke a method that
removes it, ensuring that it occurs after the event has completed.

private delegate void RemoveItemDelegate(ListViewItem item);
private void RemoveItem(ListViewItem item)
{
item.Remove();
}

private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
ListViewItem item = listView1.Items[e.Item];
listView1.BeginInvoke(new RemoveItemDelegate(RemoveItem), item);
}

/claes

"Kela" <Ke**@discussions.microsoft.comwrote in message
news:70**********************************@microsof t.com...
An interesting problem:
I have a ListView with LabelEdit set to TRUE. When I change the label, I
want to make some decisions as to whether the ListViewItem (that's just
been
edited) should stay in the ListView or not.
The natural place to inspect this is in the AfterLabelEdit event...
If the decision is to take the item out, I used the ListViewItem.Remove().
However - check this out:
A) say that the item's index is N (indices are zero-based)
B) if there exists an item after it (i.e. with index N+1)
then this item gets quietly removed
C) if the item is the last in the list,an exception is thrown
saying that index N (requested to be removed) is non-existant.

It looks like:
D) when the item is being edited, it is taken OUT of the
ListView.Items collection. So - the original item N+1 moves up and
is temporarily assigned index N (that is how it gets removed - see
B) above)
E) if however, item N is the last in the collection and gets
temporarily taken out while being edited, then of course we get
and exception thrown as there isn't an item with index N

This can easily be proved:
1. create a new Windows Forms project
2. add a ListView to the form
3. Set LabelEdit to TRUE
4. Add 3 items to the list, with labels e.g. 'Item1', 'Item2' and 'Item3'
5. Create a handler for the AfterLabelEdit event
6. Inside this handler add this code:

ListViewItem item = listView1.Items[e.Item];
item.Remove();

7. Run the application
8. Edit the first item and press Enter -the second item is removed
9. Next, edit the last item then press Enter -exception is thrown

This is all very nice...

But - can someone suggest an elegant workaround , i.e. - where and
how can I remove items after they have been edited?

Many thanks in advance.


Jul 28 '06 #2

P: n/a
Claes,
Many thanks for this. It is indeed an elegant solution.
Best Regards
Kela

"Claes Bergefall" wrote:
Actually, what really happens is this:

1. You begin editing the first item (index 0), add characters and press
Enter
2. The AfterLabelEdit event fires for index 0. At this stage the change is
*not yet commited* to the actual item
3. You remove the item with index 0
4. Control returns to Windows that now tries to commit the change to index
0. Only problem is that you removed that item so it applies it to whatever
is at index 0 now, which happens to be your second item (i.e. the one that
previously had index 1). To you this looks like the second item is removed,
while in fact the first item is removed and the second item simply gets its
text changed

Imagine what happens when you edit the last item......
(btw, you can see that the correct item is being removed if you press Esc
instead of Enter)

To work around this use BeginInvoke to asynchronously invoke a method that
removes it, ensuring that it occurs after the event has completed.

private delegate void RemoveItemDelegate(ListViewItem item);
private void RemoveItem(ListViewItem item)
{
item.Remove();
}

private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
ListViewItem item = listView1.Items[e.Item];
listView1.BeginInvoke(new RemoveItemDelegate(RemoveItem), item);
}

/claes

"Kela" <Ke**@discussions.microsoft.comwrote in message
news:70**********************************@microsof t.com...
An interesting problem:
I have a ListView with LabelEdit set to TRUE. When I change the label, I
want to make some decisions as to whether the ListViewItem (that's just
been
edited) should stay in the ListView or not.
The natural place to inspect this is in the AfterLabelEdit event...
If the decision is to take the item out, I used the ListViewItem.Remove().
However - check this out:
A) say that the item's index is N (indices are zero-based)
B) if there exists an item after it (i.e. with index N+1)
then this item gets quietly removed
C) if the item is the last in the list,an exception is thrown
saying that index N (requested to be removed) is non-existant.

It looks like:
D) when the item is being edited, it is taken OUT of the
ListView.Items collection. So - the original item N+1 moves up and
is temporarily assigned index N (that is how it gets removed - see
B) above)
E) if however, item N is the last in the collection and gets
temporarily taken out while being edited, then of course we get
and exception thrown as there isn't an item with index N

This can easily be proved:
1. create a new Windows Forms project
2. add a ListView to the form
3. Set LabelEdit to TRUE
4. Add 3 items to the list, with labels e.g. 'Item1', 'Item2' and 'Item3'
5. Create a handler for the AfterLabelEdit event
6. Inside this handler add this code:

ListViewItem item = listView1.Items[e.Item];
item.Remove();

7. Run the application
8. Edit the first item and press Enter -the second item is removed
9. Next, edit the last item then press Enter -exception is thrown

This is all very nice...

But - can someone suggest an elegant workaround , i.e. - where and
how can I remove items after they have been edited?

Many thanks in advance.


Jul 28 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.