Элемент управления WinForms CheckedListBox
имеет два поведения по умолчанию при нажатии мышью:
- Чтобы проверить/снять отметку с элемента, который требуется дважды щелкнуть по элементу. Первый щелчок выбирает элемент, а второй переключает состояние проверки.
- Кроме того, один последующий щелчок одного и того же элемента переключит это состояние элемента.
В качестве удобства я должен был позволить пользователям переключаться на выбор одним щелчком мыши. Я достиг этого, поэтому теперь поведение по умолчанию # 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 - изменения состояния на отмечены.
- При выборе текущего элемента щелкните его еще раз - состояние не изменяется. Ожидаемый: не отмечен. Нажмите несколько раз, и он, наконец, переключится.
Спасибо за чтение!