当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - How can I enable the menu items at most once?

问题描述:

Certain menu items need to be enabled only if files of a particular type exist in a specific listbox. There may be oodles of entries in that list box, but if even just one is of the file type in question, its menu item needs to be enabled. So, I've got the following code:

foreach (String pt in platypusTables)

{

if (pt.IndexOf("Duckbill") == 0)

{

menuItemSEND_Duckbills.Enabled = true;

}

if (pt.IndexOf("Platypus") == 0)

{

menuItemSEND_Platypi.Enabled = true;

}

listBoxWork.Items.Add(pt);

}

The problem is that the menu items may be enabled hundreds of times. I would prefer the elegance of being set once and once only, but can't figure out a sensible way to accomplish that. I could do this:

foreach (String pt in platypusTables)

{

if ((pt.IndexOf("Duckbill") == 0) && (!(menuItemSEND_Duckbills.Enabled)))

{

menuItemSEND_Duckbills.Enabled = true;

}

if ((pt.IndexOf("Platypus") == 0) && (!(menuItemSEND_Platypi.Enabled)))

{

menuItemSEND_Platypi.Enabled = true;

}

listBoxWork.Items.Add(pt);

}

...but I doubt that is any more performant, maybe less so. Am I stuck with the menu items being potentially enabled time and again, or is there a solution to this conundrum?

网友答案:

You could scan the collection for any strings starting with each type you're looking for. The call to Any() will stop when it finds a match, and you're enabling each menu at most once.

menuItemSEND_Duckbills.Enabled = platypusTables.Any(p => p.StartsWith("Duckbill"));
menuItemSEND_Platypi.Enabled = platypusTables.Any(p => p.StartsWith("Platypus"));

listBoxWork.DataSource = platypusTables;

I'm not sure how performant this would be, since you're scanning the same collection multiple times for the first occurrence of each string. I suppose it depends on how large the collection of strings is, and how many menu items you're enabling this way.

网友答案:

In a sense you are stuck, but that assignment isn't that expensive. The if statement wouldn't be any more efficent, as the control already does that check: Reference Source

One thing you could do is set up flags, and OR them together. For example, say you have 8 options, you could set up a binary mapping so:

Dictionary<String, byte> typeMapping = new Dictionary<String, byte>();
typeMapping.Add("FileType1", 0x01); //00000001

Means that just the last option should be turned on with that file type. Then, you could take your list:

byte finalTypes = 0x00;
foreach (string type in list.Select(f => f.FileType).Distinct())
    finalTypes |= typeMapping[type];

Then you just have to loop through that checking for the bit flag set.

byte checkByte = 0x80;
while (checkByte != 0)
{
   if (finalTypes & checkByte != 0)
      //Bit set, enable

    checkByte = checkByte >> 1;
}

That way, you only really check for enable and set the actual value once. In my experience, this is a pretty efficient way of combing/checking large numbers of flags. The only downside is that once you get above 64 options you start running out of datatypes large enough :(.

You might be able to get away with using a [Flags] Enum to do the same thing, though I believe it suffers from similar restrictions. Just something to consider in case you want to go down this route.

Really though, this is complicated, and probably not worth whatever negligible gain it might give you. Its also pretty hard to read if you don't have good comments (especially the type mapping). Just assign away!

网友答案:

If you only want to enable item (and never disable), you can use something like :

foreach (String pt in platypusTables)
{
    menuItemSEND_Duckbills.Enabled = menuItemSEND_Duckbills.Enabled || (pt.IndexOf("Duckbill") == 0);
    menuItemSEND_Platypi.Enabled = menuItemSEND_Platypi.Enabled || (pt.IndexOf("Platypus") == 0);
    listBoxWork.Items.Add(pt);
}

Another way could be using an extension method :

foreach (String pt in platypusTables)
{
    menuItemSEND_Duckbills.EnableIfNot(pt,"Duckbill");
    menuItemSEND_Platypi.EnabledIfNot(pt,"Platypus");
    listBoxWork.Items.Add(pt);
}

//extention method, supposing a MenuItem class
public static void EnableIfNot(this MenuItem menuItem, string table, string nameToSearch)
{
     if(!menuItem.Enabled && table.IndexOf(nameToSearch)==0)
     {
             menuItem.Enabled=true;
     }
}

I hope this helps

分享给朋友:
您可能感兴趣的文章:
随机阅读: