无法在 c# 中获取 winform 中的所有子菜单项
Cannot get all the submenu items in winform in c#
我有一个带有这样菜单栏的 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;
}
}
结果为:
File==>Add
File==>Open
File==>Exit
Edit==>Copy
Edit==>Cut
Help==>View Help
Help==>About
如图所示,它并未显示所有子菜单项。我试过这段代码:
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;
}
}
}
但它给出了这个错误:
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'
注意:我正在寻找一个通用的解决方案(针对任意数量的菜单项和任意数量的嵌套子菜单项),而不仅仅是针对这个问题。
提前致谢。
使用recursion.
编写一个调用自身的方法(但也会检查是否终止,因此在不需要更深入时它不会调用自身)。
这是一些代码:
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;
}
可以使用下面的通用树遍历函数,取自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();
}
}
}
使用该函数和 LINQ,获取所有菜单项很简单
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));
我有一个带有这样菜单栏的 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;
}
}
结果为:
File==>Add
File==>Open
File==>Exit
Edit==>Copy
Edit==>Cut
Help==>View Help
Help==>About
如图所示,它并未显示所有子菜单项。我试过这段代码:
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;
}
}
}
但它给出了这个错误:
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'
注意:我正在寻找一个通用的解决方案(针对任意数量的菜单项和任意数量的嵌套子菜单项),而不仅仅是针对这个问题。
提前致谢。
使用recursion.
编写一个调用自身的方法(但也会检查是否终止,因此在不需要更深入时它不会调用自身)。
这是一些代码:
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;
}
可以使用下面的通用树遍历函数,取自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();
}
}
}
使用该函数和 LINQ,获取所有菜单项很简单
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));