我正在使用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
?
答案 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;
}