Search code examples
c#winformscheckedlistbox

CheckedListBox Action ItemCheck to remove items?


When a box that is checked is unchecked I want to remove that item. The trouble is check/unchecking seems to happen after the ItemCheck method is called. So, when I remove an item that messes up the e.Index so it does the check/uncheck on the item after the one I remove or throws an error if it is the last one.

I found this: Getting the ListView ItemCheck to stop! which has the tip of resetting the e.NewValue which partially works, but it still throws an error when I remove the last item.

The reason I have not simply used one of the mouse events is that I want keyboard navigation to still be possible just in case.

Here is the code I have now.

private void checked_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.NewValue == CheckState.Unchecked)
            {
                checked.Items.RemoveAt(e.Index);
                e.NewValue = CheckState.Checked;
            }
        }

Thanks for the help


Solution

  • It sounds like the only problem you're still experiencing is the call to e.NewValue after you remove the last item, right? If that's the case, try this:

    private void checked_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (e.NewValue == CheckState.Unchecked)
        {
            checked.Items.RemoveAt(e.Index);
    
            // If there are no items left, skip the CheckState.Checked call
            if (checked.Items.Count > 0)
            {
                e.NewValue = CheckState.Checked;
            }             
        }
    } 
    

    UPDATE

    Ok - I got it to work, though I'm not sure how pretty it is. I used the SelectedIndexChanged event:

    private void checked_SelectedIndexChanged(object sender, EventArgs e)
    {
    
        CheckedListBox clb = (CheckedListBox)sender;
        int index = clb.SelectedIndex;
    
        // When you remove an item from the Items collection, it fires the SelectedIndexChanged
        // event again, with SelectedIndex = -1.  Hence the check for index != -1 first, 
        // to prevent an invalid selectedindex error
        if (index != -1 && clb.GetItemCheckState(index) == CheckState.Unchecked)
        {
            clb.Items.RemoveAt(index);
        }
    }
    

    I've tested this in VS 2010 and it works.