У меня есть CheckedListBox, где мне нужно событие после проверки элемента, чтобы я мог использовать CheckedItems с новым состоянием.
Поскольку ItemChecked запускается до обновления CheckedItems, он не будет работать из коробки.
Какой метод или событие можно использовать, чтобы получать уведомления об обновлении CheckedItems?
c#
winforms
checkedlistbox
Hultqvist
источник
источник
if not item = checkedListBox1.Items[e.Index].ToString()
По этому поводу есть много связанных сообщений StackOverflow ... Помимо решения Бранимира , вот еще два простых:
Отложенное выполнение на ItemCheck (также здесь ):
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { this.BeginInvoke((MethodInvoker) ( () => Console.WriteLine(checkedListBox1.SelectedItems.Count))); }
Использование события MouseUp :
void checkedListBox1_MouseUp(object sender, MouseEventArgs e) { Console.WriteLine(checkedListBox1.SelectedItems.Count); }
Я предпочитаю первый вариант, так как второй приведет к ложным срабатываниям (то есть срабатыванию слишком часто).
источник
The check state is not updated until after the ItemCheck event occurs
. Другое событие или непроизвольное обходное решение было бы неплохо, ИМО.Я попробовал это, и это сработало:
private void clbOrg_ItemCheck(object sender, ItemCheckEventArgs e) { CheckedListBox clb = (CheckedListBox)sender; // Switch off event handler clb.ItemCheck -= clbOrg_ItemCheck; clb.SetItemCheckState(e.Index, e.NewValue); // Switch on event handler clb.ItemCheck += clbOrg_ItemCheck; // Now you can go further CallExternalRoutine(); }
источник
ItemChecked
событие, и никто никогда не говорил, что его не существует.ItemChecking
,ItemChecked
, то вы можете использовать один последний. Но если реализован только один (ItemCheck
), он выполняет все правильно, т.е. запускает событие до того, как значение будет проверено с новым значением и индексом, предоставленным в качестве параметров. Кто хочет событие «после изменения», он может просто использовать вышеуказанное. Если вы предложите что-то Microsoft, предложите новое мероприятиеItemChecked
, а не изменение существующего: см . ОтветПолучите
CheckedListBox
и внедрите/// <summary> /// Raises the <see cref="E:System.Windows.Forms.CheckedListBox.ItemCheck"/> event. /// </summary> /// <param name="ice">An <see cref="T:System.Windows.Forms.ItemCheckEventArgs"/> that contains the event data. /// </param> protected override void OnItemCheck(ItemCheckEventArgs e) { base.OnItemCheck(e); EventHandler handler = AfterItemCheck; if (handler != null) { Delegate[] invocationList = AfterItemCheck.GetInvocationList(); foreach (var receiver in invocationList) { AfterItemCheck -= (EventHandler) receiver; } SetItemCheckState(e.Index, e.NewValue); foreach (var receiver in invocationList) { AfterItemCheck += (EventHandler) receiver; } } OnAfterItemCheck(EventArgs.Empty); } public event EventHandler AfterItemCheck; public void OnAfterItemCheck(EventArgs e) { EventHandler handler = AfterItemCheck; if (handler != null) handler(this, e); }
источник
BeginInvoke
решения из второго ответа.Хотя это и не идеально, вы можете вычислить CheckedItems, используя аргументы, которые передаются
ItemCheck
событию. Если вы посмотрите на этот пример в MSDN , вы сможете определить, был ли недавно измененный элемент отмечен или снят, что оставляет вас в подходящем положении для работы с элементами.Вы даже можете создать новое событие, которое срабатывает после проверки элемента, что даст вам именно то, что вы хотели, если хотите.
источник
После некоторых тестов я увидел, что событие SelectedIndexChanged запускается после события ItemCheck. Сохраните свойство CheckOnClick True
Лучшее кодирование
источник
Это работает, хотя не уверен, насколько это элегантно!
Private Sub chkFilters_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkFilters.ItemCheck Static Updating As Boolean If Updating Then Exit Sub Updating = True Dim cmbBox As CheckedListBox = sender Dim Item As ItemCheckEventArgs = e If Item.NewValue = CheckState.Checked Then cmbBox.SetItemChecked(Item.Index, True) Else cmbBox.SetItemChecked(Item.Index, False) End If 'Do something with the updated checked box Call LoadListData(Me, False) Updating = False End Sub
источник
Не знаю, применимо ли это, но я хотел использовать контрольный список для фильтрации результатов. Так как пользователь отмечал и не отмечал элементы, я хотел, чтобы в списке отображались \ скрывались элементы.
У меня были некоторые проблемы, которые привели меня к этой публикации. Просто хотел поделиться, как у меня получилось, без ничего особенного.
Примечание: у меня CheckOnClick = true, но, вероятно, он все равно будет работать без
Я использую событие « SelectedIndexChanged ».
я использую перечисление " .CheckedItems "
Это дает результаты, которые, я думаю, мы можем ожидать. В упрощенном виде все сводится к ....
private void clb1_SelectedIndexChanged(object sender, EventArgs e) { // This just spits out what is selected for testing foreach (string strChoice in clb1.CheckedItems) { listBox1.Items.Add(strChoice); } //Something more like what I'm actually doing foreach (object myRecord in myRecords) { if (clb1.CheckItems.Contains(myRecord["fieldname"]) { //Display this record } } }
источник
Предполагая, что вы хотите сохранить аргументы,
ItemCheck
но получать уведомление после изменения модели, это должно выглядеть так:CheckedListBox ctrl = new CheckedListBox(); ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));
Где
CheckedItemsChanged
могло быть:private void CheckedItemsChanged(object sender, EventArgs e) { DoYourThing(); }
источник
Я попробовал это, и это сработало:
private List<bool> m_list = new List<bool>(); private void Initialize() { for(int i=0; i < checkedListBox1.Items.Count; i++) { m_list.Add(false); } } private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { if (e.NewValue == CheckState.Checked) { m_list[e.Index] = true; checkedListBox1.SetItemChecked(e.Index, true); } else { m_list[e.Index] = false; checkedListBox1.SetItemChecked(e.Index, false); } }
определить по индексу списка.
источник
Я использую таймер для решения этой проблемы. Включите таймер с помощью события ItemCheck. Выполните действие в событии Timer's Tick.
Это работает независимо от того, отмечен ли элемент щелчком мыши или нажатием клавиши пробела. Мы воспользуемся тем фактом, что элемент, только что отмеченный (или не отмеченный), всегда является выбранным элементом.
Интервал таймера может составлять всего 1. К моменту возникновения события Tick будет установлен новый статус Checked.
Этот код VB.NET демонстрирует концепцию. Вы можете использовать множество вариантов. Вы можете увеличить интервал таймера, чтобы пользователь мог изменить статус проверки для нескольких элементов, прежде чем предпринимать какие-либо действия. Затем в событии Tick выполните последовательный проход всех элементов в списке или используйте его коллекцию CheckedItems для выполнения соответствующих действий.
Вот почему мы сначала отключаем таймер в событии 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
источник
В нормальном поведении, когда мы проверяем один элемент, состояние проверки элемента изменится до того, как будет вызван обработчик события. Но CheckListBox имеет другое поведение: обработчик событий вызывается до изменения состояния проверки элемента, что затрудняет исправление наших заданий.
На мой взгляд, чтобы решить эту проблему, нужно отложить обработчик событий.
private void _clb_ItemCheck(object sender, ItemCheckEventArgs e) { // Defer event handler execution Task.Factory.StartNew(() => { Thread.Sleep(1000); // Do your job at here }) .ContinueWith(t => { // Then update GUI at here },TaskScheduler.FromCurrentSynchronizationContext());}
источник