2

In my windows forms project written in C# I try to clear a CheckedListBox after the last Item is checked.

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if (checkedListBox1.CheckedItems.Count + 1 == checkedListBox1.Items.Count)
    {
        checkedListBox1.Items.Clear();
    }
}

In this example, the program would throw a NullReferenceException, after I check the last item.

Could somebody explain why this is happening and how I can handle this?

Thanks in advance!

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
EmKay89
  • 53
  • 1
  • 6
  • You should be using a try catch block, see what happens if you catch the `System.NullReference` – G. LC Sep 09 '18 at 12:04
  • This code shouldn't throw null reference exception. Perhaps, we have this exception in another event where you try to address the last item incorrectly? – Yeldar Kurmangaliyev Sep 09 '18 at 12:25
  • @G.LC The exception Message is "Object reference not set to an instance of an object.", the Source is "System.Windows.Forms" and the target site "Void SetCheckedState(Int32, System.Windows.Forms.CheckState)" – EmKay89 Sep 09 '18 at 13:15
  • @YeldarKurmangaliyev But it does! I use Visual Studio 2010 Express. You can very easily reproduce the error. Just create a new windows forms project, add a checked list box with one or more items and add the ItemCheckEvent with the code above. Once you check all boxes, it will throw an exception. – EmKay89 Sep 09 '18 at 13:20
  • 1
    How about the `StackTrace` what does that give you? From my experience with Object reference not set to an instance of an object, it is quite literal. – G. LC Sep 09 '18 at 15:13

2 Answers2

5

Change your code to run the logic after the check state of the item updated:

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    checkedListBox1.BeginInvoke(new Action(() =>
    {
        if (checkedListBox1.CheckedItems.Count == checkedListBox1.Items.Count)
        {
            checkedListBox1.Items.Clear();
        }
    }));
}

According to the documentations, by default, when the ItemCheck event raises, the check state of the item is not updated until after the ItemCheck event occurs. It means it tries to update the check state of the item after running the code that you have in the event handler. As a result in your code, it tries to update item check state after the item removed from items collection and that's why an exception happens. You can see what happens in stack trace, also in source code of the control.

In above code, using BeginInvoke we delay running the code after the check state is updated. You can read more about it in this post.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • This is working fine! Thanks a lot. As a beginner, It would have taken me weeks to figure this out. – EmKay89 Sep 09 '18 at 18:38
1

It is because after you clear the items from the checklistbox, there is some internal call (System.Windows.Forms.CheckedListBox.CheckedItemCollection.SetCheckedState) that is invoked later and still operates on the items. So it throws the NullReferenceException.

If you register the SelectedIndexChanged event instead, you can clear the items without having this problem.

The difference is the timing, ItemCheck is triggerred early, at that time you can't clear the items, and SelectedIndexChanged is triggered much later.

kennyzx
  • 12,845
  • 6
  • 39
  • 83