Check only one ListViewItem during

I am developing a smart device project using the Compact Framework.

I have a ListView with several ListViewItem s checked: the CheckBoxes property is true. I need to check only one ListViewItem , so I signed the ItemCheck event:

 // I need to know the last item checked private ListViewItem lastItemChecked; private void listView_ItemCheck(object sender, ItemCheckEventArgs e) { if (lastItemChecked != null && lastItemChecked.Checked) { /* I need to do the following to prevent infinite recursion: ie subscribe and then unsubscribe the ItemCheck event. */ listView.ItemCheck -= listView_ItemCheck; lastItemChecked.Checked = false; listView.ItemCheck += listView_ItemCheck; } lastItemChecked = listView.Items[e.Index]; } 

Is there a better way to prevent infinite recursion and therefore Stack Overflow ?

+4
source share
5 answers

Well, I think it could be better than juggling with EventHandlers, checking if lastItemCheck is the current EventArgs element. Like this:

 // I need to know the last item checked private ListViewItem lastItemChecked; private void listView_ItemCheck(object sender, ItemCheckEventArgs e) { // if we have the lastItem set as checked, and it is different // item than the one that fired the event, uncheck it if (lastItemChecked != null && lastItemChecked.Checked && lastItemChecked != listView.Items[e.Index] ) { // uncheck the last item and store the new one lastItemChecked.Checked = false; } // store current item lastItemChecked = listView.Items[e.Index]; } 

I think you will agree that re-assigning EventHandlers is a little worse than just checking the reference to a stored object.

+11
source

Here's a simpler approach that can be reused for multiple lists.

  private void listView_ItemCheck(object sender, ItemCheckEventArgs e) { var listView = sender as ListView; if (listView != null) { for (var i = 0; i < listView.CheckedItems.Count; i++) { listView.CheckedItems[i].Checked = false; } } } 

The ItemCheck event is fired before the state of a list item changes, so no additional tests are required.

ItemCheck - Indicates that the item will change its state. The value is not updated until an event occurs.

Other answers that check if the current element does not match the current element are not useful, since the selection occurs after the completion of this event, so it does not matter if the value is false.

 lastItemChecked != listView.Items[e.Index] 
+2
source

M Buck, you forgot to disable the item check event before assigning a new value. And your code will also clear the last set value because you are using a validation event. Also CheckedItems.Count will be changed after changing the Checked value. Fixed solution:

 private void LstFirstPageBanner_ItemCheck(object sender, ItemCheckEventArgs e) { var listView = sender as ListView; if (listView != null) { var checkedCount = listView.CheckedItems.Count; listView.ItemCheck -= LstFirstPageBanner_ItemCheck; for (var i = 0; i < checkedCount; i++) { listView.CheckedItems[i].Checked = false; } listView.ItemCheck += LstFirstPageBanner_ItemCheck; } } 
+1
source
 private void listView1_ItemChecked(object sender, ItemCheckedEventArgs e) { listView1.ItemChecked -= listView1_ItemChecked; foreach (var item in listView1.CheckedItems) { if (e.Item != item) { ((ListViewItem)item).Checked = false; } } listView1.ItemChecked += listView1_ItemChecked; } 
0
source

How many codes and tricks ...

 listView.SelectionMode = System.Windows.Controls.SelectionMode.Single; 
-1
source

All Articles