How can I add an event handler to an event by name

2019-09-06 13:49发布

问题:

I'm attempting to add an event handler for every control on my form. The form is a simple info box which pops up, and clicking anywhere on it does the same thing (sort of like Outlook's email notifier.) To do this, I've written a recursive method to add a MouseClick handler to each control, as follows:

private void AddMouseClickHandler(Control control, MouseEventHandler handler)
{
    control.MouseClick += handler;
    foreach (Control subControl in control.Controls)
        AddMouseClickHandler(subControl, handler);
}

However, if I wanted to add a handler for all of the MouseDown and MouseUp events, I'd have to write two more methods. I'm sure there's a way around this, but I can't find it. I want a method like:

private void AddRecursiveHandler(Control control, Event event, EventHandler handler)
{
    control.event += handler;
    foreach (Control subControl in control.Controls)
        AddRecursiveHandler(subControl, event, handler);
}

回答1:

You could pass the event name as a string and then use Reflection to implement this, but that would be quite ugly (and slow as well). Unfortunately, there is no other way to pass events as arguments to a method.

However, you can write this elegantly using lambda functions. Instead of writing function to add handler, you can write a function that calls a lambda expression for every control:

private void TraverseControls(Control control, Action<Control> f) 
{ 
    f(control); 
    foreach (Control subControl in control.Controls) 
        TraverseControls(subControl, f); 
} 

Then you can solve your original problem using a single call:

TraverseControls(form, ctl => { 
  ctl.MouseDown += handler;
  ctl.MouseUp += handler); });

The lambda expression ctl => { .. } will be called for every control in the tree and inside the lambda expression, you can add handlers to any events of the control. You could also write this using two calls (adding handlers to MouseDown in the first one and to MouseUp in the second one).

Compared to solution using Reflection, this is faster and safer.



回答2:

You can use reflection to hook up to events. Take a look at this article on MSDN



回答3:

It looks like you are on a good path. If you have an event handler in your FORM's MouseDown and MouseUp, you should just be able to attach to that like you already do in your

control.MouseClick += handler... 

just add since the signature is the same, but the action is different, you'll want to handle appropriately.

control.MouseDown += YourFormsMouseDownHandler 
control.MouseUp += YourFormsMouseUpHandler


回答4:

If you want the event to happen everywhere you do not need to add the event to every item. just add a event to the parent form (or panel if you want just the items in a panel to respond) and everything you click inside that form will fire the event from the parent object.