Нет события ItemChecked в CheckedListBox? - PullRequest
27 голосов
/ 15 декабря 2010

Элемент управления ListView имеет событие ItemCheck , которое вызывается до изменения элемента, и событие ItemChecked , которое запускается после элемент меняется. См. этот вопрос SO для более подробной информации.

Элемент управления CheckedListBox имеет только событие ItemCheck.

Каков наилучший способ сделать что-то подобное с CheckedListBox?

private void checkedListBox_ItemChecked(object sender ItemCheckedEventArgs e)
{
    okButton.Enabled = (checkedListBox.CheckedItems.Count > 0);
}

Дополнительный вопрос: Почему нет события CheckedListBox.ItemChecked?

Ответы [ 4 ]

51 голосов
/ 15 декабря 2010

Хороший трюк, чтобы справиться с событиями, которые вы не можете обработать при их возникновении, заключается в задержке обработки.Что вы можете сделать с помощью метода Control.BeginInvoke (), он запускается, как только отправляются все события, побочные эффекты завершаются и поток пользовательского интерфейса снова переходит в режим ожидания.Часто полезный и для TreeView, еще один капризный элемент управления.

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
        this.BeginInvoke((MethodInvoker)delegate { 
            okButton.Enabled = checkedListBox1.CheckedItems.Count > 0;
        });
    }

На всякий случай: это никак не связано с многопоточностью, а хитрость довольно дешевая.

Почему нет события ItemChecked?Не совсем уверен.CheckedListBox просто не очень хороший элемент управления.Определенно не сделано ни одним из гуру в оригинальной команде Winforms.

4 голосов
/ 15 декабря 2010
    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
        int count = this.checkedListBox1.CheckedItems.Count;
        if (e.CurrentValue != CheckState.Checked && e.NewValue == CheckState.Checked) {
            count += 1;
        } else if (e.CurrentValue == CheckState.Checked && e.NewValue != CheckState.Checked) {
            count -= 1;
        }
        this.okButton.Enabled = count > 0;
    }
1 голос
/ 02 сентября 2015

На основании ответа Ханса Пассанта Я добавляю общую версию VB.NET.Мне нужен был один метод, который вызывался бы для всех элементов управления CheckedListBox в форме.Вы можете легко настроить это, если вам нужны отдельные методы для каждого элемента управления (хотя добавляет некоторую избыточность).

Public Class Form1
    Delegate Sub ProcessItemCheck(ByRef ListBoxObject As CheckedListBox)

    Private Sub ProcessItemCheckSub(ByRef ListBoxObject As CheckedListBox)
        ' Do your actual ItemCheck stuff here
    End Sub

    Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
        Dim Objects As Object() = {CheckedListBox1}
        BeginInvoke(New ProcessItemCheck(AddressOf ProcessItemCheckSub), Objects)
    End Sub
End Class
0 голосов
/ 10 апреля 2015

Я использую таймер для решения этой проблемы.Включите таймер через событие ItemCheck.Выполните действие в событии Timer Tick.

Это работает независимо от того, проверяется ли элемент щелчком мыши или нажатием пробела.Мы воспользуемся преимуществом того факта, что только что отмеченный (или не отмеченный) элемент всегда является выбранным элементом.

Интервал таймера может составлять всего 1. К моменту возникновения события Tick,будет установлен новый статус Проверено.

Этот код VB.NET показывает концепцию.Есть много вариантов, которые вы можете использовать.Возможно, вы захотите увеличить интервал таймера, чтобы пользователь мог изменить статус проверки нескольких элементов, прежде чем предпринимать какие-либо действия.Затем в событии Tick выполните последовательную передачу всех элементов

в списке или используйте его коллекцию CheckedItems для выполнения соответствующих действий.

Именно поэтому мы сначала отключаем Timer в событии ItemCheck,«Отключить, затем включить» приводит к перезапуску интервала.

Private Sub ckl_ItemCheck(ByVal sender As Object, _
                          ByVal e As System.Windows.Forms.ItemCheckEventArgs) _
        Handles ckl.ItemCheck

tmr.Enabled = False
tmr.Enabled = True

End Sub


Private Sub tmr_Tick(ByVal sender As System.Object, _
                     ByVal e As System.EventArgs) _
Handles tmr.Tick

tmr.Enabled = False
Debug.Write(ckl.SelectedIndex)
Debug.Write(": ")
Debug.WriteLine(ckl.GetItemChecked(ckl.SelectedIndex).ToString)

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...