在任何情况下是否有可能实现这一目标?
我目前的情况如下:
public class CustomForm : Form
{
public class CustomGUIElement
{
...
public event MouseEventHandler Click;
// etc, and so forth.
...
}
private List<CustomGUIElement> _elements;
...
public void CustomForm_Click(object sender, MouseEventArgs e)
{
// we might want to call one of the _elements[n].Click in here
// but we can't because we aren't in the same class.
}
}
我的第一个想法是拥有类似于以下的功能:
internal enum GUIElementHandlers { Click, ... }
internal void CustomGUIElement::CallHandler(GUIElementHandler h, object[] args) {
switch (h) {
case Click:
this.Click(this, (EventArgs)args[0]);
break;
... // etc and so forth
}
}
这是一个非常难看的kludge,但它应该工作......虽然必须有一个更优雅的解决方案? .NET库一直使用消息处理程序和Control中的调用事件来执行此操作。还有其他人有其他/更好的想法吗?
答案 0 :(得分:25)
您只需添加一个公共方法来调用该事件。 Microsoft已针对某些事件执行此操作,例如 PerformClick ,用于显示 Click 事件的控件。
public class CustomGUIElement
{
public void PerformClick()
{
OnClick(EventArgs.Empty);
}
protected virtual void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
}
然后,您将在示例事件处理程序中执行以下操作...
public void CustomForm_Click(object sender, MouseEventArgs e)
{
_elements[0].PerformClick();
}
答案 1 :(得分:8)
c#中的event关键字修改了委托的声明。它阻止直接分配给委托(你只能在事件上使用+ =和 - =),它会阻止从类外部调用委托。
因此,您可以将代码更改为:
public class CustomGUIElement
{
...
public MouseEventHandler Click;
// etc, and so forth.
...
}
然后你可以像这样在课外调用这个事件。
myCustomGUIElement.Click(sender,args);
缺点是使用该类的代码可以使用以下代码非常轻松地覆盖任何已注册的处理程序:
myCustomGUIElement.Click = null;
如果将Click委托声明为事件,则不允许。
答案 2 :(得分:1)
你真的应该在方法中包装你想要能够从外部执行的代码。然后,该方法可以执行您的事件所做的任何事情 - 而该事件也会调用该方法。
答案 3 :(得分:0)
使用.NET框架的现代语法功能,可以大大缩短接受的答案中建议的代码:
public event Action<int> RecipeSelected;
public void RaiseRecpeSelected(int recipe) => RecipeSelected?.Invoke(recipe);