My question is related to events:
I have Class with a TaskAComplete Event that is raised when TaskA is complete.
When a button is pressed I subscribe the TaskACompleteEvent
MyObject.TaskAComplete += new EventHandler(MethodToCall);
But in other Event I want to Unsubscribe from the TaskAComplete Event when the Event occurs the first time.
with:
MyObject.TaskAComplete -= MethodToCall;
And then when the Button is pressed the next time to Subscribe the TaskAComplete Event again.
Now when i start the Application and click on the Button the first time it raises the Event correctly.But when i click on the Button the second time the Event is raises two times in a row. (Third time click ->Event is raised three times in a row and so on..)
When i Subscribe the Event in the Contructor of the Form it only raises one time at every click.
Why the Event comes several times?
When you subscribe to an event, you are subscribing by providing a delegate to a method. A delegate is effectively a strongly-typed, object-oriented approach to a C/C++ function pointer.
This delegate then goes into the list of calls for the event.
When you do new EventHandler(MethodToCall) you are explicitly creating that delegate. However, when you do -= MethodToCall, you are removing an "automatic" delegate. It is as if you wrote -= new EventHandler(MethodToCall). Obviously, this new delegate is not the one in the invocation list.
To do what you want, on add, you need to save the new delegate in a variable, which you can later remove. For example:
var handler = new EventHandler(MethodToCall);
MyObject.TaskAComplete += handler;
// later on
MyObject.TaskAComplete -= handler;
You only need to subscribe to the event once. If you subscribe multiple times with the same handler, that handler will be invoked multiple times just like you are seeing.
Why do you want to unsubscribe from the TaskAComplete event in the first place? If your other code is correct, you will get it exactly once for each task.
Related
My understanding about events in C# for a console application:
create a delegate that has the same signature as the event handler method in the subscriber class.
declare an event based on this delegate
raise the event
My understanding of this step is: it is simply an wrapper function where parameters are passed to the event to invoke the event handler functions pointed to by the event.
So raising the event is just invoking the wrapper function in the publish class.
Now when I create a very simple Windows form application, I am not able to apply this general concept.
Consider a WinForms application with just one button.
// registering statement
Button1.Click += new EventHandler (this.button1_click)
I can identify the first step. It is the pre-defined System.EventHandler delegate.
Click event for the button is also pre-defined. No problem with that.
event raising step : here I fail to make the connection between a console application and an Windows application.
Where is the code kept that actually RAISES the event for a WinForms application? We don't seem to have to code it.
I understand click event is raised when someone "clicks" on the button, but how is that realized in the C# code for WinForms application?
How does the compiler "just" knows that a Click event for a button means someone clicking on a button and therefore an event should be raised?
How is click event raised? How are the parameters passed to the event?
The Control class has protected function called WndProc, when the OS needs to tell the program something it generates a Message object and passes it in to the WndProc function.
That WndProc function then looks at the message and sees what kind of message it is, if it is the "mouse left button up" message it runs the the OnClick method with the correct parameters parsed out of the Message object that was passed in to WndProc.
That OnClick method is the thing that raises the event to the subscriber.
From the soruce of .NET:
The entry point of WndProc
It detecting the message type
It parsing and calling the OnClick method
It raising the Click event
Your understanding is a bit backwards. I think this is why you have issues.
You are not creating a delegate that has the same signature as the event handler method in the subscriber class.
What you are doing is declaring what a function to which to delegate execution will look like. Here is the signature for EventHandler:
public delegate void EventHandler(object sender, EventArgs e)
So, if you want a function to be able to handle delegation of the event, it must follow that signature.
Now, the class that will delegate execution to subscribers needs a reference to those functions so it can call them when the event takes place. That is why you implement an event property. It follows then that the Button class must expose this property for you to be able to "hook" your delegates:
public event EventHandler Click
(Notice this is inherited from Control)
When you register an "event handler":
Button1.Click += new EventHandler (this.button1_click)
You are essentially saying that you want this.button1_click(object sender, EventArgs e) to fire whenever the Click event is raised by the Button1 instance.
The Button1 instance will internally decide when to fire the event at which point it will use the event property to delegate execution to the subscribed functions. It will call them with the above mentioned parameters where sender will most likely be the instance itself and the EventArgs class will give you additional information about the conditions that raised the event. The property is also usually implemented to add additional checks (like if there is anything to call in the first place).
As you can see, the code that actually raises the click is internal to the implementation of the Button (or its inheritance chain). It obviously involves mouse tracking and what not, which is the benefit of using the controls by the way, unless you want to write all that detection stuff from scratch.
So I've had an argument with a friend, basically he is saying that this an event handler and I am stating that this is a method. Can you please tell me who's right, and explain what makes this an event handler, if so?
Control ctrlClick;
private void NextColour(object sender)
{
ctrlClick = sender as Control;
// More Code Here
}
Did you subscribe this method to an event like someEvent += NextColour;? Then it's an event handler. Otherwise just a method.
An event handler is a method subscribed to an event, and as it's name implies it gets called back in order to handle the occurrence of the event,once it gets notified by the event publishing mechanism.
If the method has not been subscribed to handle an event, then there is no event for it handle, meaning it's just a method ( maybe a very important one ... :) but still just a method).
I am developing an application where I assign the events for the button dynamically. Now the thing is that I wish to get all the events for the button click event as I wish to remove the previous handlers.
I tried setting the event handler to null like:
Button.Click += null;
However I received a runtime exception that null cannot be assigned.
I wish to know the events which are already attached to it so that I can remove those events.
Can anybody help me in achieving this?
You cannot assign events - only attach (+=) and remove (-=) operations are available for clients.
Since += and -= are the only operations that are permitted on an event outside the type that declares the event, external code can add and remove handlers for an event, but cannot in any other way obtain or modify the underlying list of event handlers.
A nice pattern is to have an Action removeAll declared somewhere, so you can do:
button.Click += handler
removeAll += () => button.Click -= handler
That way you've only got one variable to keep track of, and you can clear everything just by calling removeAll(), rather than keeping track of all your handlers individually and having to call -= on each of them. It's especially convenient if you've got multiple subclasses of EventHandler to deal with, since otherwise you'd have to keep track of them with multiple lists.
You can't do that (fortunately. Just imagine, that some external code removes your event handler, and your code just stops working in silent manner).
(Reflection isn't an option here, because event implementation may be differ from type to type). Usually, if you want to remove all event handlers this way, this means design error.
My UserControl contains various controls. I made an event handler for its click event. I want the event handler to fire / be called when the user clicks anywhere on my user control.
This is the method I use to add my UserControl to my WinForms application.
private void addContact(some parameters here)
{
//This is my usercontrol
contactsListItem.contactsListItem contact = new contactsListItem.contactsListItem();
//
//some codes here
//
//Adding an event handler for the click event
contact.Click += new EventHandler(contact_Click);
//Adding the UserControl to my application
flowLayoutPanel_contactsList.Controls.Add(contact);
}
The contact_Click(...) event handler should change the background of my UserControl. I have tried stepping into the code to see if the event handler fires and I found out that it doesn't fire no matter where I click on my UserControl.
I have searched through the internet. I encountered terms like delegate, subscribers and publishers.
What should I do to make the event handler for my UserControl's click event to fire?
What is the structure of your user control? Click events are not bubbled in WindForms, hence if you are clicking on a control WITHIN your user control, the latter won't fire any Click event.
EDIT:
The simplest solution is to manually bubble the event from each child by attaching a handler in your user control:
child1.Click += new EventHandler(child_Click);
child2.Click += new EventHandler(child_Click);
child3.Click += new EventHandler(child_Click);
and inside child_Click fire off your Click event:
this.OnClick(e);
You seem to be on the right track however it is not clear what your contact here is. Typically you use delegates (essentially pointers to functions) for methods that have arguments to be passed:
if (bDeleteRdClick)
DeleteRD.Click -= delegate { DeleteRDClick(this.Object); };
DeleteRD.Click += delegate { DeleteRDClick(this.Object); };
where you are sure to remove pre-existing delegates, otherwise they will 'stack-up', firing multiple methods when not required.
For the method above, using an EventHandler seems to me to be the right approach, but as I state above, a check on whether contact is of the correct type would not go unmissed:
if (this.contact.GetType() == typeof(RibbonButton))
{
RibbonButton Rb = (RibbonButton)contact;
Rb.Click += new EventHandler(contact_Click);
}
I hope this is of some help.
When must we use this operator by events? What is its usage?
Just as += subscribes you a handler to the event, -= unsubscribes it.
Use it when you no longer want a particular handler to be called when the event is raised. You often only need to use it the component raising the event is logically longer lived than the handler of the event - if you don't unsubscribe, the "event raiser" effectively has a reference to the handler, so can keep it alive longer than you want.
As noted in comments:
-= will only remove a single handler; if there are multiple handlers subscribed (even using the exact same delegate) it will still only reduce the handler count by 1. The last instance of the specified handler is the one removed. (So if you previously had handlers A, B, A, C subscribed in that order, and removed A, you'd end up with A, B, C.)
-= doesn't cause an error if the specified handler is not subscribed to the delegate already; it just ignores the request. This is true even if the event has no handlers subscribed to it at the moment.
Just as you can add event handlers via +=, you can remove them via -=.
For instance:
mybutton.Click += new EventHandler(myhandler);
You can later remove it like this:
mybutton.Click -= new EventHandler(myhandler);
...because event handlers for the same method and instance are equivalent (so you don't need to retain a reference to the handler you used with += and use that one with -=).
The += and -= operators can be used in C# to add/remove event handlers to/from one of an object's events:
// adds myMethod as an event handler to the myButton.Click event
myButton.Click += myMethod;
After the above code runs, the myMethod method will be called every time myButton is clicked.
// removes the handler
myButton.Click -= myMethod;
After the above code runs, clicking on myButton will no longer cause myMethod to be called.
You remove the Eventhandler Function.
C# Tutorial, Events and Delegates
I suspect that the background logic of the += is to add the handler to a list/array of event handlers for the given event. When -= is used, it compares your right hand argument to the list of event handlers it is holding for this event and deletes it from the list. If you do multiple += for a given event, each handler will get called.
Stated differently:
+= means add a method to the list of methods to call when the event occurs.
-= means remove the specified method from the list of methods to call.
If all are removed, the event will have no handlers and the event will be ignored.