Event logged in CheckedListBox?

The ListView control has an ItemCheck event that fires before the item changes, and an ItemChecked event that fires after the item changes. See this SO question for more details.

The CheckedListBox controller has an ItemCheck event.

What is the best way to do something like this using CheckedListBox?

private void checkedListBox_ItemChecked(object sender ItemCheckedEventArgs e) { okButton.Enabled = (checkedListBox.CheckedItems.Count > 0); } 

Additional Question: Why is there no CheckedListBox.ItemChecked event?

+25
c # winforms
Dec 15 '10 at 19:36
source share
4 answers

A good trick to deal with events that you cannot handle when they are raised is to defer processing. What you can do with the Control.BeginInvoke () method is that it fires as soon as all events are dispatched, side effects are completed, and the user interface thread is idle again. Often useful for TreeView, as well as another moody control.

  private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { this.BeginInvoke((MethodInvoker)delegate { okButton.Enabled = checkedListBox1.CheckedItems.Count > 0; }); } 

Just in case: this has nothing to do with threads, and the trick is pretty cheap.

Why is the ItemChecked event not logged? Not quite sure. CheckedListBox is just not very good control. Definitely not done by one of the gurus in the original Winforms team.

+47
Dec 15 '10 at 20:34
source share
  private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { int count = this.checkedListBox1.CheckedItems.Count; if (e.CurrentValue != CheckState.Checked && e.NewValue == CheckState.Checked) { count += 1; } else if (e.CurrentValue == CheckState.Checked && e.NewValue != CheckState.Checked) { count -= 1; } this.okButton.Enabled = count > 0; } 
+4
Dec 15 '10 at 20:00
source share

I am using a timer to solve this problem. Start the timer using the ItemCheck event. Take action at the Timer Tick event.

This works whether the item is checked with a mouse click or by pressing the space bar. We will take advantage of the fact that an item that has just been verified (or not verified) is always the selected item.

The timer interval can be as low as 1. By the time the Tick event occurs, a new status of "Checked" will be set.

This VB.NET code shows the concept. There are many options you can use. You can increase the timer interval so that the user can change the status of the check by several elements before taking action. Then in the Tick event make a sequential pass of all

Items are listed or use the CheckedItems collection to take appropriate action.

This is why we first turned off the Timer in the ItemCheck event. Disable, then Enable, causes the interval period to restart.

 Private Sub ckl_ItemCheck(ByVal sender As Object, _ ByVal e As System.Windows.Forms.ItemCheckEventArgs) _ Handles ckl.ItemCheck tmr.Enabled = False tmr.Enabled = True End Sub Private Sub tmr_Tick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles tmr.Tick tmr.Enabled = False Debug.Write(ckl.SelectedIndex) Debug.Write(": ") Debug.WriteLine(ckl.GetItemChecked(ckl.SelectedIndex).ToString) End Sub 
0
Apr 10 '15 at 2:16
source share

Based on Hans Passant Answer I am adding a general version of VB.NET. I needed one method that would be called for all CheckedListBox elements in the form. You can easily customize it if you need separate methods for each control (adds some redundancy).

 Public Class Form1 Delegate Sub ProcessItemCheck(ByRef ListBoxObject As CheckedListBox) Private Sub ProcessItemCheckSub(ByRef ListBoxObject As CheckedListBox) ' Do your actual ItemCheck stuff here End Sub Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck Dim Objects As Object() = {CheckedListBox1} BeginInvoke(New ProcessItemCheck(AddressOf ProcessItemCheckSub), Objects) End Sub End Class 
0
Sep 02 '15 at 14:14
source share



All Articles