Один флажок для проверки / снятия ВСЕХ других флажков в 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);
}

потому что, если вы добавите вторую строку, намеревающуюся быть внутри цикла, вы можете забыть добавить фигурные скобки - где программа все еще может быть скомпилирована и затруднить поиск проблемы.

Другие вопросы по тегам