检查项目后触发哪个CheckedListBox事件?

我有一个CheckedListBox,我想要一个事件检查一个项目,以便我可以使用CheckedItems与新的状态。

由于ItemChecked在CheckedItems更新之前被触发,因此它将无法正常工作。

什么样的方法或事件可以用来通知CheckedItems更新时?

你可以使用ItemCheck事件,如果你也检查被点击的项目的新状态。 这在事件参数中可用,如e.NewValue 。 如果选中了NewValue ,那么在逻辑中包含当前的项目以及合适的集合:

  private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { List<string> checkedItems = new List<string>(); foreach (var item in checkedListBox1.CheckedItems) checkedItems.Add(item.ToString()); if (e.NewValue == CheckState.Checked) checkedItems.Add(checkedListBox1.Items[e.Index].ToString()); foreach (string item in checkedItems) { ... } } 

作为另一个例子,确定在该项目被(取消)检查之后该集合是否是空的:

 private void ListProjects_ItemCheck(object sender, ItemCheckEventArgs args) { if (ListProjects.CheckedItems.Count == 1 && args.NewValue == CheckState.Unchecked) // The collection is about to be emptied: there's just one item checked, and it's being unchecked at this moment ... else // The collection will not be empty once this click is handled ... } 

有很多相关的StackOverflowpost…以及Branimir的解决scheme,这里有两个更简单的:

在ItemCheck上延迟执行 (也在这里 ):

  void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { this.BeginInvoke((MethodInvoker) ( () => Console.WriteLine(checkedListBox1.SelectedItems.Count))); } 

使用MouseUp事件 :

  void checkedListBox1_MouseUp(object sender, MouseEventArgs e) { Console.WriteLine(checkedListBox1.SelectedItems.Count); } 

我更喜欢第一个选项,因为第二个选项会导致误报(即经常发射)。

我试过这个,它的工作原理:

 private void clbOrg_ItemCheck(object sender, ItemCheckEventArgs e) { CheckedListBox clb = (CheckedListBox)sender; // Switch off event handler clb.ItemCheck -= clbOrg_ItemCheck; clb.SetItemCheckState(e.Index, e.NewValue); // Switch on event handler clb.ItemCheck += clbOrg_ItemCheck; // Now you can go further CallExternalRoutine(); } 

CheckedListBox派生并实现

 /// <summary> /// Raises the <see cref="E:System.Windows.Forms.CheckedListBox.ItemCheck"/> event. /// </summary> /// <param name="ice">An <see cref="T:System.Windows.Forms.ItemCheckEventArgs"/> that contains the event data. /// </param> protected override void OnItemCheck(ItemCheckEventArgs e) { base.OnItemCheck(e); EventHandler handler = AfterItemCheck; if (handler != null) { Delegate[] invocationList = AfterItemCheck.GetInvocationList(); foreach (var receiver in invocationList) { AfterItemCheck -= (EventHandler) receiver; } SetItemCheckState(e.Index, e.NewValue); foreach (var receiver in invocationList) { AfterItemCheck += (EventHandler) receiver; } } OnAfterItemCheck(EventArgs.Empty); } public event EventHandler AfterItemCheck; public void OnAfterItemCheck(EventArgs e) { EventHandler handler = AfterItemCheck; if (handler != null) handler(this, e); } 

虽然不理想,但可以使用传递给ItemCheck事件的参数来计算CheckedItems。 如果您在MSDN上查看此示例 ,则可以计算出新更改的项目是已选中还是未选中,这使您处于合适的位置来处理项目。

你甚至可以创build一个新的事件,在一个项目被检查后触发,这将准确地给你你想要的东西,如果你想。

经过一些testing后,我可以看到在事件ItemCheck之后触发了事件SelectedIndexChanged。 保持属性CheckOnClick True

最好的编码

这工作,但不知道它是多么优雅!

 Private Sub chkFilters_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkFilters.ItemCheck Static Updating As Boolean If Updating Then Exit Sub Updating = True Dim cmbBox As CheckedListBox = sender Dim Item As ItemCheckEventArgs = e If Item.NewValue = CheckState.Checked Then cmbBox.SetItemChecked(Item.Index, True) Else cmbBox.SetItemChecked(Item.Index, False) End If 'Do something with the updated checked box Call LoadListData(Me, False) Updating = False End Sub 

不知道这是否适用,但我想用一个清单框来过滤结果。 所以当用户选中或取消选中项目时,我希望列表显示\隐藏项目。

我遇到了一些问题,导致我这个职位。 只是想分享我没做过什么特别的事情。

注意:我有CheckOnClick = true,但它可能仍然没有工作

我使用的事件是“ SelectedIndexChanged

我使用的枚举是“ .CheckedItems

这给我想我们可能期望的结果。 所以简化归结为….

 private void clb1_SelectedIndexChanged(object sender, EventArgs e) { // This just spits out what is selected for testing foreach (string strChoice in clb1.CheckedItems) { listBox1.Items.Add(strChoice); } //Something more like what I'm actually doing foreach (object myRecord in myRecords) { if (clb1.CheckItems.Contains(myRecord["fieldname"]) { //Display this record } } } 

在正常行为中,当我们检查一个项目时,项目的检查状态将在事件处理程序提出之前发生改变。 但是CheckListBox的工作方式不同:事件处理程序在检查项目更改状态之前提高,使得难以纠正我们的工作。

在我看来,要解决这个问题,我们应该推迟事件处理程序。

 private void _clb_ItemCheck(object sender, ItemCheckEventArgs e) { // Defer event handler execution Task.Factory.StartNew(() => { Thread.Sleep(1000); // Do your job at here }) .ContinueWith(t => { // Then update GUI at here },TaskScheduler.FromCurrentSynchronizationContext());} 

将checkedlistbox的CheckOnClick属性设置为true,并尝试使用MouseUp事件。

我使用一个计时器来解决这个问题。 通过ItemCheck事件启用定时器。 在定时器的打勾事件中采取行动。

无论是通过鼠标点击还是按空格键来检查项目,这都能起作用。 我们将利用刚刚检查(或未检查)的项目始终是选定项目的事实。

定时器的间隔可以低至1.当Tick事件发生时,新的检查状态将被设置。

这个VB.NET代码显示了这个概念。 你可以使用很多变化。 您可能需要增加定时器间隔,以便用户在采取措施之前更改多个项目的检查状态。 然后在Tick事件中,对列表中的所有Items进行连续传递,或者使用CheckedItems集合采取适当的操作。

这就是为什么我们首先禁用ItemCheck事件中的Timer。 禁用然后启用导致间隔期重新开始。

 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