1

How do i attach the same event handler to additional controls in Winforms/.NET/C#?


i randomly tried perfectly logical code to accomplish what i want, but unfortunately the syntax is not valid in C#:

public MainForm()
{
   InitializeComponent();

   FixPanelMouseEnter(pnlActionCenter);
   FixPanelMouseEnter(pnlAdministrativeTools);
   FixPanelMouseEnter(pnlAutoPlay);
   FixPanelMouseEnter(pnlBackupAndRestore);
   //...snip 49 lines...
   FixPanelMouseEnter(pnlWFirewall);
   FixPanelMouseEnter(pnlWLiveLanguageSettings);
   FixPanelMouseEnter(pnlWUpdate);
}

private void FixPanelMouseEnter(Panel panel)
{
    foreach (Control ctrl in panel.Controls)
        ctrl.MouseEnter += panel.MouseEnter;
}

This invalid code causes the syntax error:

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

In this example i want the Panel's MouseEnter event to fire if the mouse enter's any control in the panel.

How do i attach the same event handler to additional controls in Winforms/.NET/C#?

The code i tried doesn't compile.

Related Questions

Community
  • 1
  • 1
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • @Oded The sensible syntax that i **tried** to use doesn't compile **The event 'MouseEnter' can only appear on the left hand side of a += or -=**. i'll change the question to bold the compile error of the code that doesn't work. – Ian Boyd Nov 17 '11 at 20:21
  • It doesn't compile because you put an event, not a handler on the right side of the `+=`. You need to subscribe to a _method_ not an _event_ (in this case `panel.MouseEnter`). – Oded Nov 17 '11 at 20:29
  • @Oded Can something like reflection be used to get the method attached to an event, and attach that method to another event? – Ian Boyd Nov 17 '11 at 20:40
  • Not a reflection expert, but I doubt it. As far as I know, reflection works on static types, so the dynamic nature of delegate invocation lists is probably not something that can be done. I would ask that as a new question, if I were you :) – Oded Nov 17 '11 at 20:42
  • @Oded i'm already three questions in, in trying to solve "quirks" in WinForms and C#. Every thing i try i'm thwarted by .NET. :( – Ian Boyd Nov 17 '11 at 20:45
  • Sorry to hear that. I am mostly a web guy, so not really a winforms expert. I don't quite understand what you are trying to achieve either. But every question should get you closer to an answer that solves your issue. – Oded Nov 17 '11 at 20:49
  • @Oded The problem, two questions back, is that if the mouse enters a control *in* the panel, then panel *itself* it not told that mouse enters. Events do not bubble up in .NET, as they do in other languages. – Ian Boyd Nov 17 '11 at 21:06
  • @Oded about reflection: had you seen the answers [here](http://stackoverflow.com/questions/1129517/c-sharp-how-to-find-if-an-event-is-hooked-up)? – sq33G Nov 18 '11 at 01:32

3 Answers3

2

Change:

ctrl.MouseEnter += panel.MouseEnter;

to

ctrl.MouseEnter += panel_MouseEnter;

Assuming the method void panel_MouseEnter already exists in your code.

I think you need to then pass the EventHandler, too:

private void FixPanelMouseEnter(Panel panel, EventHandler enterMethod) {
  foreach (Control ctrl in panel.Controls)
    ctrl.MouseEnter += enterMethod;
}

and then from your code:

FixPanelMouseEnter(pnlActionCenter, pnlActionCenter_MouseEnter);

But again, the pnlActionCenter_MouseEnter must already exist. Make sense?

LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • That doesn't compile, *"The name 'panel_MouseEnter' does not exist in the current context"* – Ian Boyd Nov 17 '11 at 20:16
  • @IanBoyd Are your creating these Panels at runtime? As noted by me and Oded, you have to have the method already written in order to subscribe to it. – LarsTech Nov 17 '11 at 20:17
  • Well i don't know how the person who's calling my helper method **FixPanelMouseEnter** is creating their panels. Strictly speaking all panels are *created* at runtime. But i don't know the name of panels in projects that haven't been written yet. – Ian Boyd Nov 17 '11 at 20:27
  • Is there a way to get that method at runtime? Would something like reflection be able to help? – Ian Boyd Nov 17 '11 at 20:41
  • I see what your are doing now. It's a slippery slope and I think [this answer](http://stackoverflow.com/questions/8159534/net-how-to-check-if-the-mouse-is-in-a-control/8170035#8170035) is your best bet. The code from this question's example doesn't even consider controls inside of controls inside your panel-- now you have to keep adding handlers recursively. As you can see, it's getting uglier and uglier. – LarsTech Nov 17 '11 at 20:55
1

If your event handler for panel.MouseEnter is called panel_MouseEnter, use this code:

private void FixPanelMouseEnter(Panel panel)
{
    foreach (Control ctrl in panel.Controls)
        ctrl.MouseEnter += panel_MouseEnter;
}

Note that the event handler needs to be a method, not an event.

This method (which could be an anonymous method) need to conform to the EventHandler delegate signature - void EventHandler(Object sender, EventArgs e).


Update:

I see now what you are trying to achieve.

Here is one way to get your code to work:

private void FixPanelMouseEnter(Panel panel, EventHandler commonHandlerForPanel)
{
    foreach (Control ctrl in panel.Controls)
        ctrl.MouseEnter += commonHandlerForPanel;
}
Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • The panels are not all called "panel". – Ian Boyd Nov 17 '11 at 20:15
  • @IanBoyd - The point here isn't about names, but about the _handler_ method name. You can subscribe `panel2.MouseEnter` to _any_ method that conforms to the delegate signature `void MethodName(object sender, EventArgs e)`. – Oded Nov 17 '11 at 20:17
  • Then i would need a way to determine the method name of the *handler*. – Ian Boyd Nov 17 '11 at 20:25
  • @IanBoyd - Seeing as you would _have_ the name (as the method would be written), I don't quite understand the issue. – Oded Nov 17 '11 at 20:25
  • @IanBoyd - Answer updated. You can pass in a delegate to your method. The events can subscribe to this delegate. – Oded Nov 17 '11 at 20:33
  • Reddog has a worthwhile comment (http://stackoverflow.com/q/8174203/12597) There may multiple methods attached to the event handler. And at the very least i need to pass an `IEnumerable` list of **EventHandlers**. – Ian Boyd Nov 17 '11 at 21:13
  • Since delegates can contain multiple "instances" in invocation lists, that might not be necessary. – sq33G Nov 18 '11 at 01:27
1

You cannot cause the event to fire. Best thing you can do is attach the same handler to all the events by using something like:

ctrl.MouseEnter += panel1_MouseEnter;

inside your loop, where panel1_MouseEnter is the event handler. It's possible even that you want to do this recursively in case you have nested panels for example.

Fredy Treboux
  • 3,167
  • 2
  • 26
  • 32
  • That's a good point, that `.Controls` collection might not contain all child `Controls`. That will require further investigation once i have a functioning method. – Ian Boyd Nov 17 '11 at 20:43