ListView复选框行为

时间:2011-06-10 18:34:08

标签: c# winforms listview

我有一个我正在为朋友修改的Winform应用程序。它有一个列表视图,并希望我为每一行添加一个复选框,并使它们互斥。因此,在我测试如何使其工作的过程中,我发现了一种奇怪的行为,而且跳跃的人可以告诉我我错过了什么。

如果我在没有选中复选框的情况下显示列表视图。当我单击复选框时,我无法检查它,但行剂量被选中。如果我点击列中的项目(在这种情况下是名称),它将被检查并选中。

无论我在哪一处点击一行,都会取消选中未选中的行中的任何复选框。这是我的小测试程序。我正在使用.NET 4


public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {
        TestListView.Items.Add("Bob");
        TestListView.Items.Add("Ann");
        TestListView.Items.Add("Frank");
    }

    void TestListView_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) {
        ListViewItem currentItem = TestListView.GetItemAt(e.X, e.Y);
        if (currentItem != null) {
            foreach (ListViewItem item in TestListView.Items) {
                if (item.Text == currentItem.Text) {
                    item.Checked = true;
                    item.Selected = !currentItem.Selected;
                }
                else 
                    item.Checked = false;
            }
        }
    }
}   

2 个答案:

答案 0 :(得分:1)

当你直接点击复选框时,似乎WinForms正在检查复选框,然后你的代码会立即撤消检查,所以你永远不会看到它。

也许您应该使用ItemCheckItemChecked事件代替MouseClick。第一个在Checked属性更改之前触发,第二个在After之后触发。

答案 1 :(得分:1)

我目前也有一个非常类似的问题,但是为了回应Timwi,不是代码正在进行取消检查。我一直在非常缓慢地执行它,当单击复选框时代码触发,它表示它已经检查过它。但是当表单恢复时,它将再次被取消选中。在阅读Timwi帖子后,他引导我回答问题。这不是未经检查的代码,但之后触发的winforms事件取消选中该框。这解决了它:

我的代码是:

private bool allowCheck = false;
private bool preventOverflow = true;

private void lstvwRaiseLimitStore_MouseClick(object sender, MouseEventArgs e)
    {
        preventOverflow = false;
        ListViewItem item = lstvwRaiseLimitStore.HitTest(e.X, e.Y).Item;
        if (item.Checked)
        {
            allowCheck = true;
            item.Checked = false;
        }
        else
        {
            allowCheck = true;
            item.Checked = true;
        }
    }

private void lstvwRaiseLimitStore_ItemChecked(object sender, ItemCheckedEventArgs e)
    {
        if (!preventOverflow)
        {
            if (!allowCheck)
            {
                preventOverflow = true;
                e.Item.Checked = !e.Item.Checked;
            }
            else
                allowCheck = false;
        }
    }

所以它正在做什么,首先我必须设置一个标志来防止溢出,否则当构建表单或取消选中窗口检查框时,它会保持循环代码并最终堆栈溢出。下一个标志是通过代码实际允许检查复选框,而不是通过其他方法。

单击它们,找到点击的位置,然后设置标志以允许检查完成。然后代码检查框并且项目检查部分启动,因为它是由我们的代码完成的,它只会重置allowcheck标志。

如果你单击一行,它什么都不做,但如果它是一个复选框,在我们代码的末尾,Windows函数启动并尝试检查该框,因为allowcheck标志为false,代码首先设置一个标志,说我已经阻止检查,然后将检查重置为初始状态。由于这已经完成,itemchecked事件再次开始,但代码已设置标志以防止它做任何事情。然后代码完成,它阻止窗口检查复选框,只允许我们的代码。

希望它有所帮助!