我通过在这里阅读你的好答案来学习,从foreach循环中删除项目并不是一个好习惯,因为它(并且我引用)“锯掉你正坐在的分支上”。
我的代码目前会从下拉列表中删除文本,但实际项目仍然存在(仅显示文本)。
换句话说,它不是删除,也可能是因为你无法从foreach循环中删除。
经过几个小时的尝试后,我无法理解这种做法。
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
//this is the foreach loop
foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
{
//This rules out seperators
if (mItem is ToolStripMenuItem)
{
ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;
//This matches the dropdownitems text to the CheckedItems String
if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
//And deletes the item
menuItem.DropDownItems.Remove(mItem);
}
}
}
}
但它没有删除,因为它在foreach循环中! 我非常感谢您的帮助,如果有人能够了解这些代码,我会非常感激:)
亲切的问候
答案 0 :(得分:5)
LINQ的乐趣!
// Loop through the checked items, same as you did.
foreach (var checkedItem in this.organizeFav.CheckedItems)
{
// Cast from IEnumerable to IEnumerable<T> so we can abuse LINQ
var matches = favoritesToolStripMenuItem.DropDownItems.Cast<ToolStripItem>()
// Only items that the Text match
.Where(item => item.Text == checkedItem.Text)
// Don't match separators
.Where(item => item is ToolStripMenuItem)
// Select the keys for the later .Remove call
.Select(item => item.Name);
// Loop through all matches
foreach (var key in matches)
{
// Remove them with the Remove(string key) overload.
favoritesToolStripMenuItem.Remove(key);
}
}
答案 1 :(得分:3)
你不需要foreach
循环 - 只需使用常规循环但反过来,从最后开始并开始。
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
//this *replaces* the foreach loop
for(int j = favoritesToolStripMenuItem.DropDownItems.Count - 1; j >= 0; j--)
{
ToolStripMenuItem menuItem = favoritesToolStripMenuItem.DropDownItems[j] as ToolStripMenuItem;
//This rules out seperators
if (menuItem != null)
{
//This matches the dropdownitems text to the CheckedItems String
if (menuItem.Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
favoritesToolStripMenuItem.DropDownItems.Remove(menuItem);
}
}
}
}
这是@ Kurresmack的代码重新排列,我只是在页面中直接编码,所以借口任何小的语法错误或任何明显我忽略的(免责声明:这是一个样本!)
您仍然可以将favoritesToolStripMenuItem.DropDownItems
视为一个类似于您的集合,但您不必使用foreach
对其进行枚举。这减少了几行代码,它起作用的原因是你以相反的顺序迭代它,你不会得到索引超出范围的异常。
答案 2 :(得分:0)
尝试这样的事情:
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
List<ToolStripItem> toRemove = new List<ToolStripItem>();
//this is the foreach loop
foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
{
//This rules out seperators
if (mItem is ToolStripMenuItem)
{
ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;
//This matches the dropdownitems text to the CheckedItems String
if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
toRemove.Add(mItem);
}
}
}
foreach(var item in toRemove)
{
favoritesToolStripMenuItem.DropDownItems.Remove(item);
}
}
答案 3 :(得分:0)
在我看来,使代码工作的方法是:
1.创建favoritesToolStripMenuItem.DropDownItems
集合类型的实例
2.在foreach
循环中,将您不想删除的所有项目添加到该集合中
3.使favoritesToolStripMenuItem.DropDownItems
指向新集合。或清除favoritesToolStripMenuItem.DropDownItems
并将新集合中的项目加载到其中。
希望这有帮助
答案 4 :(得分:0)
而不是foreach
使用反向for
- 循环:
for(int reverseIndex = myList.Count - 1; reverseIndex >= 0; reverseIndex--)
{
var currentItem = myList[reverseIndex];
if(MatchMyCondition(currentItem))
{
myList.Remove(currentItem);
}
}