CheckedListBox
使用鼠标单击时,WinForms控件有 2 个默认行为:
- 为了选中/取消选中一个项目,您需要单击一个项目两次。第一次单击选择项目,第二次切换检查状态。
- 此外,随后单击同一项目将切换该项目的选中状态。
作为一项便利功能,我需要允许用户一键切换选择。我已经实现了这一点,所以现在可以一键实现上面的默认行为#1。问题是行为#2 在单击相同(即当前选定的)项目时不再正常工作。在需要的项目之间跳转时它工作正常,但它需要在同一个项目上最多单击 4 次。
我的解决方法是如果用户重复选择同一项目,则调用两次切换逻辑。那么关于我的问题:
- 这行得通,但为什么呢?真正的根本问题是什么?
- 有没有更好的方法来实现这一点,这样我就可以让它像默认行为 #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-state 更改为已选中的项目。
- 选择当前项目后,再次单击它 - 状态不会改变。预期:未选中。单击它几次,它终于切换了。
谢谢阅读!