Элемент управления WinForms CheckedListBox
имеет 2 поведения по умолчанию при щелчке мышью:
- Чтобы проверить / снять отметку с элемента, необходимо дважды щелкнуть элемент.Первый щелчок выбирает элемент, а второй переключает состояние проверки.
- Кроме того, один последующий щелчок того же элемента переключает проверенное состояние этого элемента.
В качестве удобной функции мне нужно было разрешить пользователям переключать выбор одним щелчком мыши.Я добился этого, поэтому теперь поведение по умолчанию №1 выше достигается в один клик.Проблема в том, что поведение № 2 больше не работает правильно при нажатии на тот же (т.е. выбранный в данный момент) элемент.Он отлично работает при переходе между элементами, что желательно, но для этого требуется до 4 нажатий на один и тот же элемент.
Мой обходной путь для этого заключается в вызове логики переключения дважды , если пользовательвыбирает один и тот же элемент несколько раз.Итак, мои вопросы:
- Это работает, но почему?В чем реальная основная проблема?
- Есть ли лучший способ добиться этого, чтобы я мог заставить его работать как поведение по умолчанию # 2 без двойного вызова метода и отслеживания моего последнего выбора?
Как ни странно, отладка кода показывает, что проверенное состояние изменилось, но оно не отображается на стороне пользовательского интерфейса, пока не будет вызвано дважды.Я думал, что это может быть связано с многопоточностью, но это не повторяющееся событие, которое может быть вызвано использованием BeginInvoke
.
Вот мой код:
using System.Linq;
using System.Windows.Forms;
namespace ToggleCheckedListBoxSelection
{
public partial class Form1 : Form
{
// default value of -1 since first item index is always 0
private int lastIndex = -1;
public Form1()
{
InitializeComponent();
CheckedListBox clb = new CheckedListBox();
clb.Items.AddRange(Enumerable.Range(1, 10).Cast<object>().ToArray());
clb.MouseClick += clb_MouseClick;
this.Controls.Add(clb);
}
private void clb_MouseClick(object sender, MouseEventArgs e)
{
var clb = (CheckedListBox)sender;
Toggle(clb);
// call toggle method again if user is trying to toggle the same item they were last on
// this solves the issue where calling it once leaves it unchecked
// comment these 2 lines out to reproduce issue (use a single click, not a double click)
if (lastIndex == clb.SelectedIndex)
Toggle(clb);
lastIndex = clb.SelectedIndex;
}
private void Toggle(CheckedListBox clb)
{
clb.SetItemChecked(clb.SelectedIndex, !clb.GetItemChecked(clb.SelectedIndex));
}
}
}
Чтобы воспроизвести мой комментарий о проблеместроки, упомянутые в комментариях к коду, и выполните следующие действия:
- Щелкните элемент с индексом 2 - состояние меняется на проверено .
- С выбранным текущим элементом, щелкните по нему еще раз - состояние не изменится.Ожидается: не проверено .Нажмите его несколько раз, и он, наконец, переключится.
Спасибо за чтение!