我有一个 CheckedListBox
,希望在项目被勾选后触发事件以便使用新状态的CheckedItems
。
由于 ItemChecked
事件是在 CheckedItems
更新之前触发的,所以它默认情况下无法实现。
有哪种方法或事件可以让我在 CheckedItems
更新时得到通知?
我有一个 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());
else
checkedItems.Remove(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
...
}
这方面在StackOverflow上有很多相关的帖子...除了Branimir的解决方案,还有另外两种更简单的解决方法:
ItemCheck延迟执行(也可以看看这里):
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
this.BeginInvoke((MethodInvoker) (
() => Console.WriteLine(checkedListBox1.SelectedItems.Count)));
}
void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
{
Console.WriteLine(checkedListBox1.SelectedItems.Count);
}
我更喜欢第一个选项,因为第二个选项会导致误报(即过于频繁地触发)。
The check state is not updated until after the ItemCheck event occurs
。在我的意见中,不同的事件或非武断的解决方法会更好。 - Dunc我尝试过这个方法,它起作用了:
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();
}
ItemChecking
,ItemChecked
,那么您可以使用后者。但是如果只实现了一个(ItemCheck
),它正在正确地执行操作,即在使用新值和索引作为参数检查值之前触发事件。谁想要“更改后”事件,他们可以简单地使用上面的方法。如果向Microsoft建议什么,请建议一个新事件 ItemChecked
,而不是更改现有事件:请参见diimdeep的答案。 - miroxlav继承自 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);
}
BeginInvoke
解决方案时,您可以跳过很多额外的代码。 - Łukasƨ FronczykItemCheck
事件的参数来计算CheckedItems。如果你查看MSDN上的示例,就可以确定新更改的项目是已选还是未选,这样你就可以处理这些项目了。经过一些测试,我发现事件SelectedIndexChanged在事件ItemCheck之后触发。保持属性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
private List<bool> m_list = new List<bool>();
private void Initialize()
{
for(int i=0; i < checkedListBox1.Items.Count; i++)
{
m_list.Add(false);
}
}
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (e.NewValue == CheckState.Checked)
{
m_list[e.Index] = true;
checkedListBox1.SetItemChecked(e.Index, true);
}
else
{
m_list[e.Index] = false;
checkedListBox1.SetItemChecked(e.Index, false);
}
}
按列表的索引确定。
ItemCheck
的参数,但在模型更改后得到通知,则应该如下所示:CheckedListBox ctrl = new CheckedListBox();
ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));
其中CheckedItemsChanged
可以是:
private void CheckedItemsChanged(object sender, EventArgs e)
{
DoYourThing();
}
不知道是否适用,但我想使用一个 checklistbox 来过滤结果。当用户选中和取消选中项目时,我希望列表显示/隐藏项目。
我遇到了一些问题,导致我看到了这篇文章。只是想分享一下我如何在没有任何特殊工具的情况下完成它。
注意:我有 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
}
}
}
if not item = checkedListBox1.Items[e.Index].ToString()
- RajcheckedListBox1_ItemCheck
添加到checkedListBox1.ItemCheck
中,例如:checkedListBox1.ItemCheck += checkedListBox1_ItemCheck;
- Aipi