C# 无法在c中获取winform中的所有子菜单项#

C# 无法在c中获取winform中的所有子菜单项#,c#,winforms,menuitem,C#,Winforms,Menuitem,我有一个带有如下菜单栏的winform: File==>Add==>New Project File==>Add==>Existing Project File==>Open File==>Exit Edit==>Copy Edit==>Cut Help==>View Help Help==>About 我想获取所有菜单项和子菜单项的文本。 我尝试过以下代码: for (int i = 0; i <

我有一个带有如下菜单栏的winform:

File==>Add==>New Project  
File==>Add==>Existing Project  
File==>Open  
File==>Exit  
Edit==>Copy   
Edit==>Cut  
Help==>View Help  
Help==>About
我想获取所有菜单项和子菜单项的文本。
我尝试过以下代码:

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;
}
}
如图所示,它不会显示所有子菜单项。我尝试过以下代码:

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;

      }
   }
}


注意:我正在寻找一个通用的解决方案(针对任意数量的菜单项和任意数量的嵌套子菜单项),而不仅仅是针对这个问题。

提前感谢。

使用

编写一个调用自身的方法(但也检查终止,以便在不需要深入时不调用自身)

下面是一些代码:

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;
}
使用

编写一个调用自身的方法(但也检查终止,以便在不需要深入时不调用自身)

下面是一些代码:

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;
}

您可以使用以下常规树遍历函数,取自


您可以使用以下常规树遍历函数,取自


我使用了递归,但它会导致“堆栈溢出”,这就是为什么需要检查终止。在我添加到答案中的代码是自动的-如果
c.Controls
为空-它从不调用
GetText(c2)
。我在内部方法中使用了递归,但它会导致“stackoverflow”,我已经测试了您的方法,但它不起作用。您是否测试了您的解决方案?你能提供详细的解决方案给我吗?thanks@BlueFlower最初的代码只是为了解释递归。在您的情况下,需要ToolStripMenuItem而不是控件。我用新代码更新了我的答案。我使用了递归,但它会导致“堆栈溢出”,这就是为什么你需要检查终止。在我添加到答案中的代码是自动的-如果
c.Controls
为空-它从不调用
GetText(c2)
。我在内部方法中使用了递归,但它会导致“stackoverflow”,我已经测试了您的方法,但它不起作用。您是否测试了您的解决方案?你能提供详细的解决方案给我吗?thanks@BlueFlower最初的代码只是为了解释递归。在您的情况下,需要ToolStripMenuItem而不是控件。我用新代码更新了我的答案。
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;
}
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();
        }
    }
}
var allMenuItems = menuStrip1.Items.OfType<ToolStripMenuItem>()
    .Expand(item => item.DropDownItems.OfType<ToolStripMenuItem>());
textBox1.Text = string.Join(Environment.NewLine, allMenuItems
    .Select(item => item.OwnerItem.Text + @"==>" + item.Text));