复制一个EventHandler [英] Copying an EventHandler

查看:58
本文介绍了复制一个EventHandler的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法为我的一生解决这个问题,而我对自己感到沮丧.我有一个非常简单的问题,但我似乎找不到简单的解决方案.

在我的表格上,我有MenuStrip ToolStrip. ToolStrip 基本上只是一堆图标,其功能与各种菜单选项相同,但以更直观的方式显示.因此ToolStrip 上的这些图标之一是ToolStripDropDownButton.我想将MenuStrip菜单项之一下的项目复制到此下拉按钮.问题!

该代码不起作用:

I can''t seem to figure this one out for the life of me and I''m getting frustrated with myself. I have a fairly simple problem and I just can''t seem to find a simple solution.

On my form I have MenuStrip and a ToolStrip. The ToolStrip is basically just a bunch of icons that serve the same purpose as the various menu options, but in a more visual way. So one of these icons on the ToolStrip is a ToolStripDropDownButton. I want to copy the items from under one of the MenuStrip''s menu items to this drop down button. Problem!

This code doesn''t work:

foreach (ToolStripItem item in myToolStripMenuItem.DropDownItems)
    myToolStripDropDownButton.DropDownItems.Add(item);


因为它们不是复制菜单项而是从ToolStripMenuItem 移到ToolStripDropDownButton.

我认为我需要为ToolStripDropDownButton创建新的菜单项,并复制ToolStripMenuItem下的菜单项.

这很容易,直到我需要复制事件处理程序为止.这是主意:


because, instead of copying the menu items, they are moved from the ToolStripMenuItem to the ToolStripDropDownButton.

I figured that I''d need to create new menu items for the ToolStripDropDownButton, copies of those under the ToolStripMenuItem.

This is easy enough, until I get to the point where I need to copy the event handlers. Here''s the idea:

foreach (ToolStripItem item in myToolStripMenuItem.DropDownItems)
{
    ToolStripMenuItem newItem = new ToolStripMenuItem(item.Text);
    newItem.Click = item.Click; // problem line
    myToolStripDropDownButton.DropDownItems.Add(newItem);
}



但是引用事件处理程序的这种方式不起作用.编译器错误为:



But that way of referencing an event handler doesn''t work. The compiler error is:

The event ''System.Windows.Forms.ToolStripItem.Click'' can only appear on the left hand side of += or -=



有人请告诉我有一个简单的解决方案,因为我真的不认为这是一个复杂的问题.



Someone please tell me there is a simple solution to this because I really didn''t think it was a complex problem.

推荐答案

问题的解决方法(如果相当简单) . 您不能复制事件实例,可以复制委托实例.

事件专门设计为对委托实例引入一些限制,以使事件处理比委托更安全.成员ToolStripMenuItem.ClickControl.Click是事件,因此-特别是​​-它们不能复制.通常,即时更改事件处理程序(即事件的调用列表)的想法很难获得可靠的代码.现在,假设您和我都不是傻子.继续阅读.

您的问题很自然.您只需要从UI中提取一些动作即可.在单击按钮,单击主菜单项或单击上下文相关菜单项时,可能会发生相同的操作;在最后一种情况下,上下文菜单的相同实例可能会根据上下文而有所不同.您可能会遇到非常复杂的事件流,这些事件会影响所有这些控件:它们可以被隐藏,重命名或禁用.您对该技术的要求是使其全部从UI控件/项目中抽象出来:隐藏,重命名或禁用应该是抽象操作,而不是UI控件/项目;这样,与相同抽象动作相关联的控件/项目将始终保持一致的行为,而无需自动使用任何临时编程.

因此,请完全按照以下步骤操作:引入…的概念,让我命名为CommandAction(不要与(System.Action)混用.CommandAction的类型应包括委托实例(请记住,我和你不是傻瓜,因此我们可以允许这样做),一些状态信息(当前名称,是否启用,是否隐藏),可以封装在一个状态字中的任何其他状态(使用位映射枚举)以及对UI元素的引用容器:例如,包含一个Control实例和一个ToolStripMenuItem实例的容器.创建一个包含CommandAction项的容器.每当您向命令操作中添加控件/项的实例时,相应的UI Click事件是分配给适当的CommandAction实例的委托.在每个命令之后,进行全局更新,该更新应根据CommandAction实例的状态更新所有UI元素.

这只是一个草图.这样,我们在抽象动作和UI之间创建了松散耦合.对语义行为进行编码时,应仅与CommandAction容器一起使用,而不应直接与UI控件/项目一起使用.使用委托实例时,您将有更多的自由(请记住,我和您都不是傻瓜).

现在,让我们更深入.为了使事情变得更加一致并从根本上摆脱即席编程,您需要研究以下建筑设计模式:
模型视图控制器:http://en.wikipedia.org/wiki/模型视图控制器 [ ^ ],
Model-view-presenter: http://en.wikipedia.org/wiki/Model-view-presenter [< ^ ],
模型视图适配器:http://en.wikipedia.org/wiki/模型视图适配器 [^ ],
模型视图ViewModel: http://en.wikipedia.org/wiki/Model_View_ViewModel [ http://en.wikipedia.org/wiki/Loose_coupling [ ^ ].

祝你好运,
—SA
The resolution of the problem if fairly easy. You cannot copy event instances, you can copy delegate instances.

Events are designed exclusively to introduce some limitations over delegate instances, in order to make event handling more fool-proof then delegates. The members ToolStripMenuItem.Click and Control.Click are events, so — in particular — they cannot copy. In general, the idea to change event handlers (that is event''s invocation lists) on the fly hardly can get robust code. Now, let''s assume you and me are not fools. Keep reading.

Your problem is very natural. You simply need to have some set of actions abstracted from the UI. Same action can happen on the button click, main menu item click or context sensitive menu item click; in the last case the same instance of the context menu can behave differently depending on the context. You can have pretty complex flow of events which effect all those controls: they can get hidden, renamed or disabled. Your requirement to the technology is to make it all abstracted from the UI controls/items: hidden, renamed or disabled should be abstract actions, not UI controls/items; in this way controls/items associated with identical abstract actions would behave consistently without using any ad-hoc programming, automatically.

So, do exactly this: introduce a notion of… let me name it — CommandAction (not to mixed with (System.Action). The type of CommandAction should include delegate instance (remember, me and you are not fools, so we can allow it), some status information (current name, enabled or not, hidden or not, any other states which you can encapsulate in one status word (use bit-mapped enumeration) and a containers of references to UI elements: for example, a container of instances of Control and instances of ToolStripMenuItem. Make some container of CommandAction items. Each time you add an instance of control/item to a command action, the appropriate UI Click event is "assigned" to the delegate of appropriate CommandAction instance. After each command, make a global update which should update all UI elements based on the status of the instances of CommandAction.

This is just a sketch. In this way, we created loose coupling between abstract actions and UI. When you code semantic behavior, you should work only with your container of CommandAction and never directly with UI controls/items. You will have more freedom while working with delegate instances (remember, me and you are not fools).

Now, let''s go deeper. To make things even more consistent and go away from ad-hoc programming even more fundamentally, you need to study the following architectural design patterns:
Model–view–controller: http://en.wikipedia.org/wiki/Model–view–controller[^],
Model-view-presenter: http://en.wikipedia.org/wiki/Model-view-presenter[^],
Model–view–adapter: http://en.wikipedia.org/wiki/Model–view–adapter[^],
Model View ViewModel: http://en.wikipedia.org/wiki/Model_View_ViewModel[^].

On loose coupling, read http://en.wikipedia.org/wiki/Loose_coupling[^].

Good luck,
—SA


尝试一下.
Try this.
newItem.Click += item_Click // This should actually be the Method name of the Event Handler.


您要尝试做的就是告诉编译器一个Controls事件是另一个Controls事件.事实并非如此(永远不可能如此).相反,两个事件应使用相同的方法处理.


What you are trying to do is tell the compiler that one Controls Event is the other Controls Event. This is not the case (and can never be the case). Instead, both Events should be Handled by the same Method.


好,所以对于任何感兴趣的人,这都是我最终想出的解决方案.它可能不是最优雅的,但是它解决了我的问题,并且我已经花了足够的时间来准备继续前进.只是以为读过此书的其他人可能会发现它的价值.
OK, so for anyone interested, here is the solution that I eventually came up with. It is probably not the most elegant but it solves my problem and I''ve spent enough time on it already that I''m quite ready to move on now. Just thought someone else who reads this might find it of value.

foreach (ToolStripMenuItem item in myToolStripMenuItem.DropDownItems)
{
    ToolStripMenuItem newItem = new ToolStripMenuItem(item.Text);
    newItem.Name = item.Name;
    newItem.Click += new EventHandler(newItem_Click);
    myToolStripDropDownButton.DropDownItems.Add(newItem);
}



然后这就是处理新创建项目的click事件的方法:



And then this is what the method looks like that handles the click event of the newly created items:

void newItem_Click(object sender, EventArgs e)
{
    myToolStripMenuItem.DropDownItems[(sender as ToolStripMenuItem).Name].PerformClick();
}



因此,基本上,对于myToolStripMenuItem.DropDownItems中的每个ToolStripMenuItem ,我都创建了一个新的ToolStripMenuItem ,该文本和名称具有相同的名称和名称,但是所有单击事件均由相同的方法处理.然后,该方法根据ToolStripMenuItem的名称触发原始myToolStripMenuItem.DropDownItems中相应ToolStripMenuItem PerformClick()方法.



So basically, for each ToolStripMenuItem in myToolStripMenuItem.DropDownItems, I create a new ToolStripMenuItem with the same text and name but all having their click events handled by the same method. That method then fires the PerformClick() method of the corresponding ToolStripMenuItem in the original myToolStripMenuItem.DropDownItems, based on the name of the ToolStripMenuItem.


这篇关于复制一个EventHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆