Один флажок для проверки / снятия ВСЕХ других флажков в CheckedListBox (C# winForms)
У меня есть CheckListBox с 5 CheckBox, и я хочу, чтобы первым было "Все". Я записал этот код, но получаю бесконечный цикл:
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"... рекурсивно... в результате получается бесконечный цикл, где выбранным всегда является "Все", все еще "Не проверено", и я начинаю с 1 еще раз. Как я могу решить это?
2 ответа
Обратите внимание, что в этом коде используется первый элемент списка в качестве 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);
}
}
Я попытался взглянуть на твой код и 2 вещи, которые приходят мне в голову:
1) Причина в том, что привязка ItemCheck была к chkListBx, а не к конкретной строке, поэтому при изменении проверки элемента для определенной строки он снова вызвал бы этот метод - обнаружение выбранного значения и вызовите метод еще раз. Я смог заставить его работать, изменив привязку на "SelectedIndexChanged" - хотя вам может понадобиться проверить, работает ли она с остальным кодом.
2) При изменении привязки на "SelectedIndexChanged", поведение, которое я получил, было немного противоположным (то есть: все было по-прежнему не проверено, а все остальные флажки были отмечены). Причина была в том, что, когда он был ранее не отмечен - когда я щелкал по нему, он устанавливал значение "Проверено" - и, таким образом, при его оценке - значение считалось проверкой - и он "отменял выбор" всех,
NB: С другой стороны, лучше всегда иметь фигурные скобки даже для одной строки
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);
}
потому что, если вы добавите вторую строку, намеревающуюся быть внутри цикла, вы можете забыть добавить фигурные скобки - где программа все еще может быть скомпилирована и затруднить поиск проблемы.