在C#中动态筛选菜单(ContextMenuStrip),而不重新创建菜单?
这可能吗 我计划有10个菜单项,其中将有子菜单项(仅1级深度)。我希望能够在用户输入我的在C#中动态筛选菜单(ContextMenuStrip),而不重新创建菜单?,c#,.net,winforms,contextmenu,contextmenustrip,C#,.net,Winforms,Contextmenu,Contextmenustrip,这可能吗 我计划有10个菜单项,其中将有子菜单项(仅1级深度)。我希望能够在用户输入我的文本框控件时过滤它们。我知道我可以在第一次打开菜单时过滤项目,但我希望能够随着用户类型不断过滤项目,并在类别菜单项没有适用于当前过滤器的子项目时动态隐藏类别(按名称过滤) 有什么想法吗?如果不希望toolstrip对象的Visible属性出现,请将其设置为false。例如,我使用web表单应用程序完成了此操作 foreach (Control c in Page.Form.Controls)
文本框
控件时过滤它们。我知道我可以在第一次打开菜单时过滤项目,但我希望能够随着用户类型不断过滤项目,并在类别菜单项没有适用于当前过滤器的子项目时动态隐藏类别(按名称过滤)
有什么想法吗?如果不希望toolstrip对象的Visible属性出现,请将其设置为false。例如,我使用web表单应用程序完成了此操作
foreach (Control c in Page.Form.Controls)
{
//Response.Write("WORD2" + c.GetType());
if (c is Panel)
{
foreach (Control p in c.Controls)
{
if (p is CheckBoxList)
{
foreach (ListItem li in ((CheckBoxList)p).Items)
{
li.Selected = false;
}
}
}
}
}
我添加了一个上下文菜单条(menuStrip1)。为此,我添加了以下内容:
File
Exit
Edit
Copy
Paste
Further Down
Help
Arghhhh!
private void FilterMenuText_TextChanged(object sender, EventArgs e)
{
foreach (ToolStripMenuItem menuItem in menuStrip1.Items)
{
if (menuItem.DropDownItems.Count > 0)
{
bool matchFound = false;
foreach (ToolStripMenuItem childMenuItem in menuItem.DropDownItems)
{
if (childMenuItem.Text.ToUpper().Contains(FilterMenuText.Text.ToUpper()))
{
matchFound = true;
break;
}
}
menuItem.Visible = matchFound;
}
}
}
然后,我添加了一个文本框(FilterMenuText),并在ContextChanged事件上执行以下操作:
File
Exit
Edit
Copy
Paste
Further Down
Help
Arghhhh!
private void FilterMenuText_TextChanged(object sender, EventArgs e)
{
foreach (ToolStripMenuItem menuItem in menuStrip1.Items)
{
if (menuItem.DropDownItems.Count > 0)
{
bool matchFound = false;
foreach (ToolStripMenuItem childMenuItem in menuItem.DropDownItems)
{
if (childMenuItem.Text.ToUpper().Contains(FilterMenuText.Text.ToUpper()))
{
matchFound = true;
break;
}
}
menuItem.Visible = matchFound;
}
}
}
这将根据子菜单项的内容酌情隐藏和显示顶级菜单项。如果您的菜单有多个级别的下拉列表,请将foreach放入递归函数中,如:
private void FilterMenuText_TextChanged(object sender, EventArgs e)
{
foreach (ToolStripMenuItem menuItem in menuStrip1.Items)
{
menuItem.Visible = MenuItemHasChildWithName(menuItem, FilterMenuText.Text);
}
}
private bool MenuItemHasChildWithName(ToolStripMenuItem menuItem, string name)
{
if (!menuItem.HasDropDownItems)
{
return false;
}
bool matchFound = false;
foreach (ToolStripMenuItem childMenuItem in menuItem.DropDownItems)
{
if (childMenuItem.Text.ToUpper().Contains(name.ToUpper()))
{
matchFound = true;
break;
}
if (childMenuItem.HasDropDownItems)
{
matchFound = MenuItemHasChildWithName(childMenuItem, name);
if(matchFound) { break; }
}
}
return matchFound;
}
这就是我用来在上下文菜单上有条件地显示菜单项的方法。如果您使用相同的菜单并且不想显示它,您只需将同一循环中的每个项目设置为true
private void dgViewData_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (dgViewData.HitTest(e.X, e.Y).Type != DataGridViewHitTestType.ColumnHeader)
{
foreach (ToolStripMenuItem menuItem in conMicImport.Items)
{
menuItem.Visible = menuItem.Text.ToString().Contains("Add") == true ? false : true;
}
conMicImport.Show(dgViewData, e.Location);
ctxtDG = dgViewData;
}
}
}
您是否可以在compentlevel中根据文本框或其名称检查其类型?您始终可以禁用不需要的菜单项。在我的应用程序中,我只是动态创建了菜单。是的,我没有设计师的支持,但这是相当容易做到的。唯一让我感到困扰的是,菜单确实比正常的菜单位置弹出了至少10或20个像素。谢谢DJ,我不知道你的评论是什么意思,但我不需要检查类型,只是菜单项。我将做一些实验。我的意思是,如果它是一个文本框,你的文本框控件的类型或名称将被替换为我的带有标签等的示例CheckListbox。。。您可以在菜单项上执行相同的检查。我给你这个作为起点。。同样的事情也适用于windows窗体,只需将Page.Form.Controls替换为Form.Controls hanks,这看起来不错。顺便说一句,你为什么用上而不用下?习惯的力量。有人曾经提到ToUpper速度更快(因此它在我曾经参与的一个项目中被广泛使用),但事实并非如此。ToUpper()已优化,但ToUpper()和ToLower()是一个选择问题。在可能的情况下,我使用String.Compare,但在本例中,您希望查看键入的字母是否是名称的一部分,因此使用了Contains。严格地说,对于cluture不变量比较()来说,IndexOf可能是一个更好的选择,但我很懒。