Reputation: 2298
I have a Menu Strip in Windows Forms with the following structure, named mstMain
:
And I'm doing a for
loop to remove all items in Programs
(named mnuPrograms
) where the number of items is == 0
. My attempt is:
for (int n = 0; n < mnuPrograms.MenuItems.Count; n++)
if (mnuPrograms.MenuItems[n].MenuItems.Count == 0)
mnuPrograms.MenuItems.Remove(mnuPrograms.MenuItems[n]);
And it doesn't remove the correct items. I have used foreach
too:
foreach (
MenuItem item in
mnuPrograms.MenuItems.Cast<MenuItem>().Where(item => item.MenuItems.Count == 0))
mnuPrograms.MenuItems.Remove(item);
But in this case I receive a InvalidOperationException
. How can I perform this?
Upvotes: 0
Views: 1273
Reputation: 3179
You are modifiying the list while you are looping through it.
And pid is right, you may disable an item rather than delete it.
Upvotes: 3
Reputation: 11607
On a Usability point of view, you might prefer to disable the items. Users want to see that they cannot do something. By removing them they may get confused. Once you disable the items your problem might already be solved.
EDIT:
You also have a false assumption that denotes a deeper misunderstanding. You are doing two things:
You shouldn't do both because termination conditions become unpredictable (NP-incomplete under circumstances) if you don't have an invariant set over which you enumerate. That's why a foreach
will throw an exception if you modify the enumerated set inside the block.
To avoid this you should increment only when you don't remove, but at that point a while()
is more elegant, much like this:
while (i < list.Count)
{
// do stuff with list[i]
if (removal_condition) // only do one of these, never both
{
list.RemoveAt(i);
}
else
{
i++;
}
}
Upvotes: 2