C# 一次只选中一个ListViewItem

C# 一次只选中一个ListViewItem,c#,winforms,events,listview,compact-framework,C#,Winforms,Events,Listview,Compact Framework,我正在使用Compact框架开发一个智能设备项目 我有一个ListView,其中有几个可选中的ListViewItems:property复选框为true。我一次只需要检查一个ListViewItem,因此我订阅了ItemCheck事件: // I need to know the last item checked private ListViewItem lastItemChecked; private void listView_ItemCheck(object sender, Item

我正在使用Compact框架开发一个智能设备项目

我有一个
ListView
,其中有几个可选中的
ListViewItem
s:property
复选框
为true。我一次只需要检查一个
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];
}

是否有更好的方法来防止无限递归,从而防止堆栈溢出?

好吧,我认为比使用EventHandler更好的方法是检查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比简单地检查存储对象的引用更糟糕。

这么多代码和技巧

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

这里有一种更简单的方法,可用于多个列表

private void listView_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            var listView = sender as ListView;
            if (listView != null && e.NewValue == CheckState.Checked)
            {
                foreach (ListViewItem checkedItem in listView.CheckedItems)
                {
                    checkedItem.Checked = false;
                }
            }
        }
ItemCheck事件在列表项状态更改之前激发,因此不需要额外的测试


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

M Bak在分配新值之前,您忘记禁用项目检查事件。 并且您的代码也将取消选中上次选中的值,因为您使用的是选中的事件。 此外,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;
        }
    } 
private void LstFirstPageBanner\u ItemCheck(对象发送方,ItemCheckEventArgs e)
{
var listView=发送方作为listView;
如果(listView!=null)
{
var checkedCount=listView.CheckedItems.Count;
listView.ItemCheck-=LstFirstPageBanner\u ItemCheck;
对于(变量i=0;i
@BaliC为什么这样更好?你是什么意思?我用谷歌搜索了一下,这是第一个结果。Balic我需要一个更好的例子(并且解释为什么更好),而不仅仅是另一个谷歌例子……你可以考虑只在ListVIEWTest.Engest[Engult]中存储LasiTimeChalk。然后条件会更简单:如果(lastItemChecked!=null&&lastItemChecked!=listView.Items[e.Index]){…}我认为这只适用于WPFOld线程,但是。。。这显然会导致StackOverflow,这是前面方法的全部要点。不确定这是如何产生正面投票的。谢谢@AlePorro,我当时确实在本地进行了这项工作,但你是对的。我在这里发布的内容似乎不完整,这很尴尬,我添加了新的价值检查,这应该解决问题,避免对最后检查的项目进行不必要的额外跟踪。
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;
        }
    }