我有一个父控件(主窗体)和一个子控件(用户控件)。子控件有一些代码,用于确定应用程序可以执行的功能(例如保存文件,写日志等)。我需要根据功能显示/隐藏,启用/禁用主窗体的主菜单项。因为我不能只写MainMenu.MenuItem1.Visible = false;
(主菜单在子控件中不可见),我在子控件中触发一个事件并在主窗体上处理此事件。问题是我需要传递菜单中需要显示/隐藏的元素。为此,我创建了一个枚举,显示如何处理项目
public enum ItemMode
{
TRUE, FALSE, NONE
}
然后我创建了我的eventargs,它有6个ItemMode
类型的参数(我需要管理6个菜单项)。因此,每当我需要显示第一项,隐藏第二项并且不做任何其他事情我必须写这样的东西
e = new ItemModeEventArgs(ItemMode.TRUE, ItemMode.FALSE, ItemMode.NONE, ItemMode.NONE, ItemMode.NONE, ItemMode.NONE);
FireMyEvent(e);
这对我来说似乎太多代码了,更重要的是,如果我将来需要管理10个项目怎么办?然后我将重写所有构造函数只是为了增加4个NONE。
我相信有更好的方法可以做到这一点,但我无法弄清楚它是什么。
答案 0 :(得分:2)
您可以创建一个EventArgs
,其中ItemMode[]
或List<ItemMode>
或Dictionary<string, ItemMode>
代表这些项目(而不是当前的6个参数) - 这样你就不会添加更多项目时需要进行更改...
答案 1 :(得分:1)
链子 - >父母可以颠倒。在这种情况下,请求将从mainform传递到其子控件。
参与命令处理的控件必须实现一个特殊的接口:
interface ICommandHandler
{
bool CanInvoke(int commandId);
void InvokeCommand(int commandId);
bool UpdateCommand(int commandId, MenuItem item);
}
这种方法的优点是只能遍历活动控件,而不是所有子项。 弱点 - UpdateCommand()方法,可以从Application.Idle事件或计时器调用。
希望这会有所帮助
答案 2 :(得分:0)
嗯,除非在特定情况下,否则我不能用“最佳”方式说话,因为通常有几种同样好的方法。不过,我的第一个想法是创建一个具有属性的类,父类为其分配MainMenu
的引用,并且具有启用/禁用单个菜单或项的功能。在一个非常简单的情况下,这可以像传递一个字符串列表一样简单,如"OptionsScreen=enabled"
等,然后在类中手动处理这些情况,更像通用字符串,如"mnuToolsOptions=enabled"
和然后通过.Name
属性查找菜单项。因此,在启动时,创建菜单处理程序类的实例,然后执行类似MenuHandlerHelper.MenuToHandle = MainMenuStrip;
的操作。
在子级方面,您可能会让您的类更新MainMenu
派生UserObjects
,该类派生自您创建的具有public MyMainMenuHandlerHelper MenuHandlerHelper
属性的公共属性,并设置为在您的父窗体的构造函数中,所以子控件可以调用菜单更新功能。或者,您可以发送一个事件,该事件仅传回包含所有规则的List<string>
,并按照您现在正在执行的操作进行解雇。
这是一个非常简单的想法,并且不处理可能的冲突之类的事情,因此您可能要么抛出异常(最简单)。您可能还希望拥有规则优先级(简单),或尝试链接功能(可能难以确定订单等)。
我很乐意实现我思考的一些例子,如果你可以为我稍微约束问题(希望碰撞处理等),我实际上想看看一些基本代码会是什么样子并尝试测试一些想法,所以如果有任何想法,我会在这里发布代码。
答案 3 :(得分:0)
如果要处理来自用户控件的所有更改:您可以继承自己的用户控件类,并添加对您希望能够修改的菜单项的表单/集合的引用。您可以将此引用传递给它的构造函数,然后您就可以从用户控件中轻松修改菜单
另一方面,如果您希望在表单中以事件为基础管理它,您可以实现自己的EventArgs类,但我会这样做:
class ItemModeEventArgs
{
MenuItemClass target;
EnumType change;
}
所以基本上每个菜单项都会出现一个单独的事件。每个事件都知道什么项目菜单正在改变以及它是如何变化的。 Ofc,如果菜单项只有两种状态,则“更改”字段有点无用。 这样您就不必使用n个参数对函数进行硬编码,其中n是菜单项的数量。
答案 4 :(得分:0)
真的有很多方法可以做到。最简单的方法,虽然有人会喊出“不好的做法”,但是在创建控件时只需将指针传递给主菜单。你的控件会有这样的代码:
MenuStrip MainMenu;
internal void SetMainMenu(MenuStrip mainMenu)
{
MainMenu = mainMenu;
}
并在创建控件时:
void CreateControl()
{
MyUserControlType MyControl = new MyUserControlType();
MyControl.SetMainMenu(mainMenuStrip); //or whatever you called your main menu
}
这将使您的孩子能够无限制地访问主题的菜单(这就是为什么它在技术上是一种不好的做法)。从子表单中,您可以按名称访问子菜单,例如:
if (MainMenu != null)
{
ToolStripMenuItem fileMenu =
(ToolStripMenuItem)MainMenu.Items["fileToolStripMenuItem"];
fileMenu.DropDownItems["exportFileToolStripItem"].Visible = false;
}
如果您在设计器中创建了控件,则可以将SetMainMenu调用添加到.design文件中,或将其添加到Form的加载事件中。