i am using textchanged event and i disable it where i don't need as following
object.Event -= new System.EventHandler(myHandler);
//my code which doesn't need event handler
object.Event += new System.EventHandler(myHandler);
i used many times like this. but i needed sometimes 2 disable code like this:
object.Event -= new System.EventHandler(myHandler);
object.Event -= new System.EventHandler(myHandler);
of course i finished it with 2 enable code
object.Event += new System.EventHandler(myHandler);
object.Event += new System.EventHandler(myHandler);
i don't know yet why i needed 2 times remove event handler but it worked great.
but in 1 case i got problem.
it doesn't work with 2 or more disable code.
my question is, how can i watch this eventhandler if it needs just one -= code or more?
or how can i manage it?
i always worked like this, to make sure that i always leave event handler as first time
object.Event -= new System.EventHandler(myHandler);
//my code which doesn't need event handler
object.Event += new System.EventHandler(myHandler);
My advice would be to stop removing and re-adding the event handler, and instead add a flag to your event handler itself which inhibits whatever activities you need to inhibit during these sections of code.
You can either have a single boolean flag, or use some kind of reference count, depending on how you need to cope with nesting.
If there's some reason why you can't change the existing event handler, what about creating a new event hander which you attach to Event, and call the old one from that?
You need to remove an event handler as many times as you've added it - and you won't be able to tell when that is, as the subscriptions are effectively hidden from you.
Ideally, just make sure you only subscribe as many times as you need to, and it should be obvious how many times you need to unsubscribe too. Usually this will be once. It's somewhat odd that you ended up with two subscriptions to start with... I suspect that may indicate a bug somewhere in your code.
Note that unsubscribing using an event handler which isn't already subscribed is a no-op.
(Will's idea of the event handler itself knowing whether or not it's really "active" is a good one too, btw.)
Related
I have an event handler that for some reason (I don't understand) get called twice, I thought that setting e.Handled = true will solve it but it doesn't, finally I unsubscribed from the event inside the handler, and it works:
((FabTabItem)sender).TabClosing -= oTab_TabClosing;
So I have these questions:
What is the difference between the both approches, Don't they stop handling the event?
Is it OK to unsubscribe from the event inside its handler since its natural to say "stop listening to the event after it's been handled"? (I don't see this a lot)
From the following MSDN page on the KeyPressEventArgs.Handled Property:
If the event is not handled, it will be sent to the operating system for default processing.
So setting it to true means that any further processing of the event will not happen for the rest of that call to the event depending on how the other events handle the Handled property. As #Enigmativity put it in the comments to the OP:
When you have several handlers for the one event they are called in series. If one of the handlers thinks that it has "handled" the event and no further handlers need to do anything it can set e.Handled = true. It is up to the subsequent handlers to honour this flag and not do any processing - but they are still called. Also this doesn't change the handling for when the next time the event is raised - all of the handlers get called again.
By unsubscribing from the event the rest of the actions in the event still occur, in the case of the above mentioned event it still goes through to the operating system.
The two scenarios you described are not exactly the same.
Unsubscribing from the event inside the handler itself is fine, all it does is remove the call to that handler next time the event is raised.
With that said if you are doing this because the event is being called more times than it should be you should probably track down where the event is being subscribed too. It is likely you have accidentally subscribed the same handler twice and that is the proper fix rather than hacking around it by unsubscribing from the event.
What is the difference between the both approaches, Don't they sop handling the event?
e.Handled = true; indicates that the event handler has already processed the event and dealt with it, so it doesn't need to be processed any further. In other words, please don't take any further action.
but the second will Remove Event and Don,t happen next time
Is it OK to unsubscribe from the event inside its handler since its natural to say "stop listening to the event after it's been handled"? (I don't see this a lot)
its depend to your Roll if you want not happen after a If use handle but if you want never happen after if use second
and remove event
Have a simple application with a start/stop button that I want to do different things depending on it's current state. If button is in Start state, execute code then change to stop state and change OnClick event to StopButton_Click and vice versa.
Can't seem to change the on-click property of the button, so using code below which works, but keeps adding instances of the event. First click executes once, second click executes twice, third executes four times, ad infinitum.
StartButton.Click += new System.EventHandler(StartButton_Click);
alternates with
StartButton.Click += new System.EventHandler(StopButton_Click);
Is there a way to REPLACE the OnClick handler instead of adding to it?
Try removing the event handler before adding a new one:
StartButton.Click -= StartButton_Click;
One option is to remove the previous event handler before adding another, but a simpler option is to just use a single event handler. The event handler can look at some internal state field to determine what to do; this will likely be easier than constantly adding/removing event handlers.
It may look something like this:
private void buttonClick(object sender, EventArgs args)
{
if(buttonState == MyStateEnum.Start)
PerformStartAction();
else if(buttonState == MyStateEnum.Stop)
PerformStopAction();
}
Then instead of adding/removing event handlers you just need to assign a different value to buttonState.
+= works with events as it does anything else. It adds to what is already there.
Try removing the existing event handler with -= and then adding the new one.
I want to conditionally unhook an event handler. Is this the right way to do it:
tb.TextChanged -= textBoxIntName_TextChanged;
?
This seems to be sensible, as hooking it up required:
tb.TextChanged += textBoxIntName_TextChanged;
...but it also seems that what corresponds to the "Delphi way" makes as much or more sense (but alas, it does not compile):
tb.TextChanged = nil;
You cannot assign events - only attach (+=) and remove (-=) operations are available for clients.
Read more about events here.
Also C# specification says:
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.
In some cases I have found, developers unwire event then wire it again like this:
control.Click -= new eventHandler(eventHandler)
control.Click += new eventHandler(eventHandler)
why do they do that?
Possibly because there is other code in between that will trigger the event, and they don't want eventHandler to act on it. IMHO this isn't the best way to do things, but it's easy and it works.
If there is no other code in between there cannot possibly be a reason to remove and add the same event handler again.
I can explain this in a simple screnerio.
Imagine you have a "button1"
And you added the event on the run-time.
But once this button is clicked. The process behind it take let say "3Mins" to complete.
And you don't want the user to click this button again.
So you can do by Unwiring it in the first time.
So that the person don't click the button again and again. And adding the instruction in the queue.
If you call code that wires an event, and you don't wont to accidentally wire it up again if it was already wired, you can unwire, and then rewire it. This is the code sample above.
If it wasn't already wired in the first place, no error is thrown. But if the code had already been run first, you don't wont the event to run twice. Thus, unwire and then rewire.
I have a command button on a winform. So, if I have something like:
myButton.Click += MyHandler1;
myButton.Click += MyHandler2;
myButton.Click += MyHandler3;
How can I tell if any particular MyHandler has already been added to the Click event so it doesn't get added again somewhere else in my code?
I've read how you can use GetInvocationList() for your own event's information. But I get errors when trying to get the items for my command button using various combinations. It says,
"The event
'System.Windows.Forms.Control.Click'
can only appear on the left hand side
of += or -=."
What am I missing?
[Edit] - I'd like to accentuate this question that Ahmad pointed out. It's a kludge and should be easier IMHO, but it looks like it might just work.
If you're in doubt if your handler is already added then just remove it and add it again. If your handler wasn't added in the first place, your removal is just ignored.
myButton.Click -= MyHandler1;
myButton.Click += MyHandler1;
You could also create one method for attaching to an event, and make sure that the code is only run once.
private bool handlersAdded;
private void AddHandlers()
{
if (this.handlersAdded) return;
myButton.Click += MyHandler1;
this.handlersAdded = true;
}
The use of GetIvocationList can only be done from within the owner of the event (myButton in your case), that's one of the ideas behind events (as opposed to delegates).
Like Slugster said, you can't check the invocation list from outside myButton, but you can try and remove MyHandler# before adding it.