问题
I have a checkedListBox with 5 CheckBoxes, and I want the first one to be "All". I wrote down this code but i'm getting an endless loop:
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 --------------
// -----------------------------------------------
}
The Bold line (**) unfortunately Calls "chkLstBx_ItemCheck" again... recursively... resulting in an endless loop where the selected is always "All", still "Unchecked", and i begins at 1 once more. How can I solve this?
回答1:
In this code, notice that this uses the first item in the list as the All
item. This is a good practice but a better one is to keep the reference for the all item and use it to check which item is checked in the event handler.
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);
}
}
回答2:
I've tried to look at your code and 2 things that comes to my mind:
1) The reason being is that the binding for ItemCheck was against the chkListBx and not the specific row, as such when you are changing the item check of a specific row, it would call this method again -- finding what was the selected value and call the method again. I was able to make it work by changing the binding to 'SelectedIndexChanged' -- although you may need to check if it works with the rest of your code.
2) When changing the binding into 'SelectedIndexChanged', the behaviour that I got was a little bit of the opposite (ie: the All was still unchecked and all the other checkbox was checked). The reason being was that when it was previously unchecked -- when I clicked it, it set the value to 'Checked' -- and thus when it was being evaluated - the value was considered check -- and it goes to 'unselect' all.
NB: On a side note, its better to always have the braces even for a single line
for (int i = 1; i < chkLstBx.Items.Count; i++)
chkLstBx.SetItemChecked(i, false);
into
for (int i = 1; i < chkLstBx.Items.Count; i++)
{
chkLstBx.SetItemChecked(i, false);
}
because if you add a second line intending to be within the loop, you may forgot adding the braces - where the program may still be compile and make it hard to find issue.
来源:https://stackoverflow.com/questions/46449044/one-checkbox-to-check-uncheck-all-other-checkboxes-in-checkedlistbox-c-winform