Reputation: 11756
public void DeliverEvent(object sender, EventArgs e)
{
}
public void StartListening(Button source)
{
source.Click += DeliverEvent;
}
public void StartListening(EventHandler eventHandler)
{
eventHandler += DeliverEvent;
}
But in #2, you cannot call the method because if you try something like this:
StartListening(button.Click);
You get this error:
The event 'System.Windows.Forms.Control.Click' can only appear on the left hand side of += or -=
Is there any way around that error? I want to be able to pass the event and not the object housing the event to the StartListening
method.
Upvotes: 3
Views: 3494
Reputation: 81159
Unfortunately, although events and properties in .net exist in the type system, and while it would have been both possible and useful for Microsoft to make them exist as concrete types (each instance would contain a pair of delegates, either for add/remove or for get/set), Microsoft has not created any such concrete types nor does it seem likely to do so. Consequently, there is no remotely-nice-looking way to pass a property or event to a routine. Instead, for events, one would either have to pass a pair of delegates--one for an Add
method and one for a Remove
method, or else possibly pass a class or struct which holds the two delegates in question, or else pass the object whose events should be used along with the name of the event, and have the called routine use Reflection to locate the add/remove handlers associated with the named event.
Upvotes: 0
Reputation: 236218
You can't pass event as parameter, because it's not an object of delegate type. Event is a pair of two methods - add
and remove
.
I.e. Click
event of button class actually looks like
public void add_Click(EventHandler value)
{
// combine delegate
}
public void remove_Click(EventHandler value)
{
// remove delegate
}
If you want to subscribe to event, you should pass whole object and then call add
method for that particular event (use +=
syntax).
Upvotes: 1
Reputation: 117064
The Microsoft Reactive Extensions or Rx framework provides a method to turn an event into an observable. Events cannot be passed around as parameters, but observables can. When observables are subscribed to they set up handlers for the underlying event.
The signature (of one of the overloads) looks like this:
IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(
Action<TDelegate> addHandler, Action<TDelegate> removeHandler
) where TEventArgs: EventArgs
For example, to define a MouseMove
observable from an event this code can be used:
IObservable<EventPattern<MouseEventArgs>> mouseMoves =
Observable
.FromEventPattern<MouseEventHandler, MouseEventArgs>(
h => richTextBox1.MouseMove += h,
h => richTextBox1.MouseMove -= h);
You can then pass around a reference to IObservable<EventPattern<MouseEventArgs>> mouseMoves
and subscribe to it like so:
var subscription =
mouseMoves
.Subscribe(ep =>
{
var x = ep.EventArgs.X;
var y = ep.EventArgs.Y;
// etc
});
Detaching from the observable/event becomes as simple as calling this:
subscription.Dispose();
You can get Rx via Nuget.
Upvotes: 1
Reputation: 13177
You are mixing events with delegates. You should probably read this article by Jon Skeet which will explain the differences between the two.
The reason the second option doesn't work is because the method expects a parameter that is a delegate that conforms to the EventHandler
signature.Button.Click
refers to an event rather than a delegate. Events just encapsulate delegates.
I'm not sure what you are trying can be done. Conceptually what you want to do doesn't actually make sense; it is the logic of the handler you want to pass around not the event itself.
Take a look at this post which looks at some ways of simulating the effect you want.
Upvotes: 1