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!
只需添加一个或减去一个取决于e.NewValue==CheckState.Checked
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!
Rather do the following:
int checkedcount = 0;
foreach(var item in checkedListBox1.CheckedItems){
if(checkedListBox1.GetItemCheckState(checkedListBox1.Items.IndexOf(item) == System.Windows.Forms.CheckState.Checked)
checkedcount++;
}
For further reference look here.
链接地址: http://www.djcxy.com/p/69912.html