Странное поведение при переключении состояния отмеченного элемента CheckedListBox с помощью MouseClick при щелчке по тому же выбору

Элемент управления WinForms CheckedListBox имеет 2 поведения по умолчанию при щелчке мышью:

  1. Чтобы установить / снять отметку с элемента, вам необходимо щелкните элемент дважды. Первый щелчок выбирает элемент, а второй переключает состояние проверки.
  2. Кроме того, один последующий щелчок того же элемента переключит отмеченное состояние этого элемента.

В качестве удобной функции мне нужно было позволить пользователям переключать выбор одним щелчком. Я добился этого, поэтому теперь поведение по умолчанию №1, описанное выше, достигается одним щелчком мыши. Проблема в том, что поведение №2 больше не работает правильно при нажатии на тот же (т. Е. Текущий выбранный) элемент. Он отлично работает при переключении между элементами, что необходимо, но для этого требуется до 4 щелчков по одному и тому же элементу.

Мой обходной путь для этого - вызвать логику переключения дважды , если пользователь выберет то же самое. пункт повторно. Итак, к моим вопросам:

  1. Это работает, но почему? Какой' - настоящая основная проблема?
  2. Есть ли лучший способ добиться этого, чтобы я мог заставить его работать как поведение по умолчанию №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));
        }
    }
}

Чтобы воспроизвести мою проблему, закомментируйте строки, упомянутые в закодируйте комментарии и выполните следующие действия:

  1. Щелкните элемент с индексом 2 - состояние изменится на отмечено .
  2. Выбрав текущий элемент, щелкните его еще раз - состояние не изменится. Ожидается: не отмечен . Щелкните его несколько раз, и он наконец переключится.

Спасибо за чтение!

24
задан Ahmad Mageed 3 November 2010 в 02:13
поделиться