Cannot get all the submenu items in winform in c#

末鹿安然 提交于 2021-01-28 07:06:34

问题


I have a winform with menu bar like this :

File==>Add==>New Project  
File==>Add==>Existing Project  
File==>Open  
File==>Exit  
Edit==>Copy   
Edit==>Cut  
Help==>View Help  
Help==>About

I want to get the text of all menu items and submenu items.
I have tried this code :

for (int i = 0; i < menuStrip1.Items.Count; i++)
{
foreach (ToolStripMenuItem item in ((ToolStripMenuItem)menuStrip1.Items[i]).DropDownItems)
{
  textBox1.Text += item.OwnerItem.Text + @"==>" + item.Text + Environment.NewLine;
}
}

and it results to :

 File==>Add  
 File==>Open   
 File==>Exit  
 Edit==>Copy  
 Edit==>Cut  
 Help==>View Help  
 Help==>About  

as it shows it does not show all of submenu items. I have tried this code :

for (int i = 0; i < menuStrip1.Items.Count; i++)
{
  for (int j = 0; j < ((ToolStripMenuItem) menuStrip1.Items[i]).DropDownItems.Count; j++)
  {
     foreach (ToolStripMenuItem item in (ToolStripMenuItem)menuStrip1.Items[i]).DropDownItems[j]))
     {
      textBox1.Text += item.OwnerItem.Text + @"==>" + item.Text + Environment.NewLine;

      }
   }
}

but it gives this error :

foreach statement cannot operate on variables of type 'System.Windows.Forms.ToolStripItem' because 'System.Windows.Forms.ToolStripItem' does not contain a public definition for 'GetEnumerator'   



Note : I am looking for a general solution(for the arbitrary number of menu item and arbitrary number of nested sub menu items) not only for this problem.

Thanks in advance.


回答1:


Use recursion .

Write a method that calls itself (but checks for termination as well so it does not call itself when not needed to go deeper).

Here is some code:

static string GetText2(ToolStripMenuItem c)
{
    string s = c.OwnerItem.Text + @"==>" + c.Text + Environment.NewLine;
    foreach (ToolStripMenuItem c2 in c.DropDownItems)
    {
        s += GetText2(c2);
    }
    return s;
}



回答2:


You can use the following general tree traversal function, taken from How to flatten tree via LINQ?

public static class TreeHelper
{
    public static IEnumerable<T> Expand<T>(this IEnumerable<T> source,
        Func<T, IEnumerable<T>> elementSelector)
    {
        var stack = new Stack<IEnumerator<T>>();
        var e = source.GetEnumerator();
        try
        {
            while (true)
            {
                while (e.MoveNext())
                {
                    var item = e.Current;
                    yield return item;
                    var elements = elementSelector(item);
                    if (elements == null) continue;
                    stack.Push(e);
                    e = elements.GetEnumerator();
                }
                if (stack.Count == 0) break;
                e.Dispose();
                e = stack.Pop();
            }
        }
        finally
        {
            e.Dispose();
            while (stack.Count != 0) stack.Pop().Dispose();
        }
    }
}

With that function and LINQ, getting all the menu items is simple

var allMenuItems = menuStrip1.Items.OfType<ToolStripMenuItem>()
    .Expand(item => item.DropDownItems.OfType<ToolStripMenuItem>());

and producing a text like in your example

textBox1.Text = string.Join(Environment.NewLine, allMenuItems
    .Select(item => item.OwnerItem.Text + @"==>" + item.Text));


来源:https://stackoverflow.com/questions/33766276/cannot-get-all-the-submenu-items-in-winform-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!