Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to track checks in checkedListBox C#?

I try to display the number of checked items in the checkedListBox: checkedListBox1.CheckedIndices.Count But how can i update my count, if i want to display it on label? I tried to write all in the ItemCheck event:

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {            
        label1.Text= checkedListBox1.CheckedIndices.Count;
    }

But the count increases even if i uncheck the item :( I'd appreciate any help!

like image 692
Gyuzal R Avatar asked Mar 09 '13 11:03

Gyuzal R


1 Answers

The documentation for CheckedListBox.ItemCheck event states that:

The check state is not updated until after the ItemCheck event occurs.

so when the event is called, the CheckedIndices.Count is not yet updated. To overcome this, you have to subclass the CheckedListBox class and fire a new event after the CheckedListBox.ItemCheck event:

public class MyCheckedListBox : CheckedListBox
{
    public event ItemCheckEventHandler ItemCheckedChanged;
    protected virtual void OnItemCheckedChanged(ItemCheckEventArgs ice)
    {
        var h = ItemCheckedChanged;
        if (h != null)
            h(this, ice);
    }

    protected override void OnItemCheck(ItemCheckEventArgs ice)
    {
        base.OnItemCheck(ice);

        ThreadPool.QueueUserWorkItem(new WaitCallback((state) =>
            {
                this.BeginInvoke(new Action<ItemCheckEventArgs>(OnItemCheckedChanged), ice);
            }));
    }

No you have a ItemCheckedChanged event that you can subscribe to.

Actually there is no need to subclass. This can be done in the form itself, but this is cleaner.

How does it work?

The ItemCheck event is called inside the SetItemCheckState method. This method changes the check state of the item after calling the event (OnItemCheck). Also calling SetItemCheck is a consequence of a windows message that is passed to the message queue of the application. We want our message to be fired after this message is processed, so we have to post a new message into the queue, so that our message is processed after this message. The BeginInvoke method actually posts a message into the message queue, but only if called from another thread. That's why I called BeginInvoke in a new thread form thread pool.

Another solution to this could be registering a message and manually posting it to the message queue, but that would be a lot more code!

like image 85
Mohammad Dehghan Avatar answered Oct 05 '22 05:10

Mohammad Dehghan