Calling C# events from outside the owning class?
Solution 1
You just need to add a public method for invoking the event. Microsoft already does this for some events such as PerformClick for controls that expose a Click event.
public class CustomGUIElement
{
public void PerformClick()
{
OnClick(EventArgs.Empty);
}
protected virtual void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
}
You would then do the following inside your example event handler...
public void CustomForm_Click(object sender, MouseEventArgs e)
{
_elements[0].PerformClick();
}
Solution 2
The event keyword in c# modifies the declaration of the delegate. It prevents direct assignment to the delegate (you can only use += and -= on an event), and it prevents invocation of the delegate from outside the class.
So you could alter your code to look like this:
public class CustomGUIElement
{
...
public MouseEventHandler Click;
// etc, and so forth.
...
}
Then you can invoke the event from outside the class like this.
myCustomGUIElement.Click(sender,args);
The drawback is that code using the class can overwrite any registered handlers very easily with code like this:
myCustomGUIElement.Click = null;
which is not allowed if the Click delegate is declared as an event.
Solution 3
You can shorten the code suggested in the accepted answer a lot using the modern syntax feature of the .NET framework:
public event Action<int> RecipeSelected;
public void RaiseRecpeSelected(int recipe) => RecipeSelected?.Invoke(recipe);
Solution 4
You really should wrap the code you want to be able to execute from the outside in a method. That method can then do whatever your event would do - and that event would also instead call that method.
Comments
-
Matthew Scharley almost 2 years
Is it possible under any set of circumstances to be able to accomplish this?
My current circumstances are this:
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. } }
My first thought was to have a function similar to:
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 } }
It's a horribly ugly kludge, but it should work... There must be a more elegant solution though? The .NET library does this all the time with message handlers and calling events in Control's. Does anyone else have any other/better ideas?