CheckedListBox 中 check/uncheck 所有其他复选框的一个复选框 (C# winForms)

One checkBox to check/uncheck ALL other checkBoxes in CheckedListBox (C# winForms)

我有一个带有 5 个复选框的 checkedListBox,我希望第一个是 "All"。 我写下了这段代码,但我得到了一个无限循环:

private void chkLstBx_ItemCheck(object sender, ItemCheckEventArgs e)
{
    // ----- Get the name of the CheckBox that's changed: -----
    string selected = chkLstBx.SelectedItem + "";
    // ----- If "All" changed: -----
    if (selected.Equals("All"))
        // ----- to TRUE(from unchecked): -----
        if (("" + (chkLstBx.GetItemCheckState(0))).Equals("Unchecked"))
            for (int i = 1; i < chkLstBx.Items.Count; i++)
                **chkLstBx.SetItemChecked(i, true);**
        else // ----- to FALSE(from checked): -----
            for (int i = 1; i < chkLstBx.Items.Count; i++)
                chkLstBx.SetItemChecked(i, false);
// -----------------------------------------------
// -------------- REST OF CODE HERE --------------
// -----------------------------------------------
}

粗体行 (**) 不幸的是再次调用 "chkLstBx_ItemCheck"...递归...导致无限循环,其中选择的始终是 "All",仍然是 "Unchecked",我再次从 1 开始。 我该如何解决?

在这段代码中,请注意,它使用列表中的第一项作为 All 项。这是一种很好的做法,但更好的做法是保留所有项目的引用,并使用它来检查在事件处理程序中检查了哪个项目。

private void chkLstBx_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if (e.Index == 0)
    {
        if (e.NewValue == CheckState.Checked)
            ChangeAllCheckBoxValues(true);
        else
            ChangeAllCheckBoxValues(false);
    }
}

private void ChangeAllCheckBoxValues(bool value)
{
    for (int i = 1; i < chkLstBx.Items.Count; i++)
    {
        chkLstBx.SetItemChecked(i, value);
    }
}

我已尝试查看您的代码并想到了两件事:

1) 原因是 ItemCheck 的绑定是针对 chkListBx 而不是特定行的,因此当您更改特定行的项目检查时,它会再次调用此方法 - 找到什么是选定的值并再次调用该方法。我能够通过将绑定更改为 'SelectedIndexChanged' 来使其工作——尽管您可能需要检查它是否适用于您的其余代码。

2) 将绑定更改为 'SelectedIndexChanged' 时,我得到的行为有点相反(即:“全部”仍未选中,所有其他复选框均已选中)。原因是当它之前未被选中时——当我点击它时,它会将值设置为 'Checked'——因此当它被评估时——该值被认为是检查——它会变为 'unselect'全部。

注意:附带说明,最好始终使用大括号,即使是单行

for (int i = 1; i < chkLstBx.Items.Count; i++)
            chkLstBx.SetItemChecked(i, false);

进入

for (int i = 1; i < chkLstBx.Items.Count; i++)
{
    chkLstBx.SetItemChecked(i, false);
}

因为如果你添加第二行打算在循环内,你可能会忘记添加大括号 - 程序可能仍在编译并且很难找到问题。