WinFormsCheckedListBox
コントロールには、マウスでクリックしたときの2つのデフォルトの動作があります。
- アイテムをチェック/チェック解除するには、アイテムを2回クリックする必要があります。最初のクリックでアイテムを選択し、2回目のクリックでチェック状態を切り替えます。
- さらに、同じアイテムを1回クリックすると、そのアイテムのチェック状態が切り替わります。
便利な機能として、ユーザーがワンクリックで選択を切り替えることができるようにする必要がありました。私はこれを達成したので、上記のデフォルトの動作#1がワンクリックで達成されます。問題は、同じ(つまり現在選択されている)アイテムをクリックしたときに動作#2が正しく機能しなくなることです。目的のアイテム間をジャンプする場合は正常に機能しますが、同じアイテムを最大4回クリックする必要があります。
これに対する私の回避策は、ユーザーが同じアイテムを繰り返し選択した場合に、トグルロジックを2回呼び出すことです。だから私の質問に:
- これは機能しますが、なぜですか?本当の根本的な問題は何ですか?
- これを実現するためのより良い方法はありますか?メソッドを2回呼び出したり、最後の選択を追跡したりせずに、デフォルトの動作#2のように機能させることができますか?
奇妙なことに、コードをデバッグすると、チェックされた状態が変更されたことがわかりますが、2回呼び出されるまでUI側には表示されません。スレッドに関連している可能性があると思いましたが、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の項目をクリックします-状態がチェック済みに変わります。
- 現在のアイテムを選択した状態で、もう一度クリックします。状態は変わりません。期待される:チェックされていない。数回クリックすると、最終的に切り替わります。
読んでくれてありがとう!