一次只检查一个ListViewItem

时间:2012-12-13 11:09:53

标签: c# winforms events listview compact-framework

我正在使用Compact Framework开发智能设备项目。

我有一个ListView有几个可检查的ListViewItem:属性CheckBoxes是真的。我需要在时间只检查一个ListViewItem,所以我订阅了ItemCheck事件:

// I need to know the last item checked
private ListViewItem lastItemChecked;

private void listView_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if (lastItemChecked != null && lastItemChecked.Checked)
    {
        /* I need to do the following to prevent infinite recursion:
        i.e. subscribe and then unsubscribe the ItemCheck event. */
        listView.ItemCheck -= listView_ItemCheck;
        lastItemChecked.Checked = false;
        listView.ItemCheck += listView_ItemCheck;
    }

    lastItemChecked = listView.Items[e.Index];
}

是否有更好的方法来阻止无限递归,从而阻止Stack Overflow

5 个答案:

答案 0 :(得分:11)

好吧,我认为比使用EventHandlers更好的方法是检查lastItemCheck是否是EventArgs中的当前项。像这样:

// I need to know the last item checked
private ListViewItem lastItemChecked;

private void listView_ItemCheck(object sender, ItemCheckEventArgs e)
{
    // if we have the lastItem set as checked, and it is different
    // item than the one that fired the event, uncheck it
    if (lastItemChecked != null && lastItemChecked.Checked
        && lastItemChecked != listView.Items[e.Index] )
    {
        // uncheck the last item and store the new one
        lastItemChecked.Checked = false;
    }

    // store current item
    lastItemChecked = listView.Items[e.Index];
}

我认为您同意,重新分配EventHandler比仅仅检查存储对象的引用要差一些。

答案 1 :(得分:2)

这是一种更简单的方法,可以重复用于多个列表。

    private void listView_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        var listView = sender as ListView;
        if (listView != null)
        {
            for (var i = 0; i < listView.CheckedItems.Count; i++)
            {
                listView.CheckedItems[i].Checked = false;
            }
        }
    }

ItemCheck事件在列表项状态更改之前触发,因此不需要其他测试。

ItemCheck - 表示项目即将更改其选中状态。事件发生后才会更新该值。

另一个回答检查当前项目是否与当前项目不匹配没有任何用处,因为在此事件完成后进行选择,因此如果将其设置为false则无关紧要。

lastItemChecked != listView.Items[e.Index]

答案 2 :(得分:1)

M Bak您忘记在分配新值之前禁用项目检查事件。 并且您的代码也将取消选中上次检查的值,因为您使用了checked事件。 Checked值更改后,CheckedItems.Count也会更改。 固定的解决方案是:

private void LstFirstPageBanner_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        var listView = sender as ListView;
        if (listView != null)
        {
            var checkedCount = listView.CheckedItems.Count;
            listView.ItemCheck -= LstFirstPageBanner_ItemCheck;
            for (var i = 0; i < checkedCount; i++)
            {
                listView.CheckedItems[i].Checked = false;
            }
            listView.ItemCheck += LstFirstPageBanner_ItemCheck;
        }
    } 

答案 3 :(得分:0)

这么多代码和技巧......

listView.SelectionMode = System.Windows.Controls.SelectionMode.Single;

答案 4 :(得分:0)

private void listView1_ItemChecked(object sender, ItemCheckedEventArgs e)
    {
        listView1.ItemChecked -= listView1_ItemChecked;
        foreach (var item in listView1.CheckedItems)
        {
            if (e.Item != item)
            {
                ((ListViewItem)item).Checked = false;

            }

        }
        listView1.ItemChecked += listView1_ItemChecked;
    }