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);
}
因为如果你添加第二行打算在循环内,你可能会忘记添加大括号 - 程序可能仍在编译并且很难找到问题。
我有一个带有 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);
}
因为如果你添加第二行打算在循环内,你可能会忘记添加大括号 - 程序可能仍在编译并且很难找到问题。