I dynamically add and remove TextChanged event:
TextBox.TextChanged -= new System.EventHandler(this.textBox_TextChanged);
........
TextBox.TextChanged += new System.EventHandler(this.textBox_TextChanged);
How can I know at some moment if this event was attached or detached?
There is no way to determine if an event was ever attached or removed, particularly not from an event in a class you didn't define. An event defined in another class can only appear on the left side of an add/remove operation - attempting to do otherwise will result in the compiler telling you as much as an error.
If you want to know about this for some reason that can't be better suited otherwise, consider instead raising a flag when attaching this even handler, so that you can query said flag later.
Related
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.
that is a question I have been asking myself for a while.
Giving a certain flow of events, can I when handling one of them, stop the next ones to be raised?
For example, when collapsing a node which child was selected in a treeview (winform), the events are raised like that:
BeforeCollapse
BeforeSelect
AfterSelect
AfterCollapse
I could stop them by using a class member, but I was wondering whether there was a built-in function or just another way (a more elegant way) to achieve this, by acting directly on the events queue.
Any idea?
Not easily, no. The order of the events firing is controlled by the TreeView control class, and there is no built-in way to prevent events from firing. But you have a couple of options:
Create your own TreeView class that inherits from the base class,
then add a bool property to prevent the events from processing.
Then you can override BeforeCollapse, etc. to check the bool
before calling base.BeforeCollapse.
Just create a bool flag, and check the flag in each of the events.
No there is no way to do that for that type of event (you are asking for TreeView).
Like for example could be managed KeyEventArgs.Handled via built-in mechanism.
You can use some instance (boolean ?) value to manage the flow,
or you can, unsubscribe from the event that you don't want more recieve, but after subscribe to it again. Sounds rough solution, but sometimes turns out reasonable one.
even if the event are raised nothing will happen if you don't bind an event handler to them. In this case you can just remove the handler using the code below:
object.Event -= new EventHandlerType(your_Method)
Otherwise you should create your own custom control
according to OnBeforeCollapse you get an TreeViewCancelEventArgs which has an Cancel property. Setting this to true should stop the flow, but will also not collapse it.
Same goes for OnBeforeSelect.
The only times you can easily "cancel" an event is if the event handler has the CancelEventHandler delegate type. Even then it doesn't really cancel it as much as set a flag for the remaining events that makes it skip performing all the events subscribed to it.
If you did have a CancelEventHandler type (which these don't) you'd simply set Cancel to true on the event object itself in the handler.
Plenty of other answers give you suggestions for what you should o. I'd just go with your idea: set a 'event cancelled' flag in your control class, and check it. When the last event in the series gets called, reset it.
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.
Can you write code to tell an event not to fire? Sometimes in my applications events fire unexpectedly. I know this is a broad question, but it must have happened to others out there.
You could put an if-statement in your event handler around all the code or you could dynamically detach and reattach the event handlers from outside the event handler, if necessary.
But really, events don't just fire without reason. You probably have something else going on. Maybe you can explain more what the situation is?
There is no standard way to suppress an "unexpected" event. But you could remove all of the event handlers. This is rather drastic, but would be equivalent to suppressing the event.
Alternatively you could add code to the event handlers to do nothing when the event is fired unexpectedly. This assumes you can define "unexpected".
Rather than suppress an event, a better approach is to remove/suppress whatever is that's causing the event to fire.
Here's what I am working with:
Part of my project is a windows form app. I want to basically capture every event that fires and has listeners. So some button's click event, some checkbox's check event, everything on a basic "Control" event list. So that event still fires, but also fires my event.
Is there a generic "some event fired" event under the hood I can tap into, or is there a way using reflection to enumerate through all objects in my form, parse out all the events, parse which have listeners, and then subscribe all of them to a generic event elsewhere in addition to where they are already going?
Anyone know how to do this?
You fundamentally can't do this: an event is a black box with just "subscribe" and "unsubscribe" functionality. So while you can use reflection to find out all the events, you can't reliably detect which have been subscribed to. For field-like events you could fetch the backing field and check whether or not it's null, but even that's not reliable - to avoid null checks, the author may have written something like this:
public event EventHandler SomeEvent = delegate {};
For other events, you'd have to work out what subscribing to the event actually does - for example, it might use EventHandlerList.
Basically, you should rethink your design so you don't need to do this.
Doesn't the fact that a subscribed event got fired indicate it has subscriber(s)? So then all you would need is a list of subscribable events, which you can validate against during an intercepted call.
You can intercept a call using any AOP framework. For instance, by using Unity Interception, you can do something like this:
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
// 1. assuming that you are keeping a list of method names
// that are being subscribed to.
// 2. assuming that if the event is fired, then it must have
// been subscribed to...
if (MyReflectedListOfSubscribedEvents.Contains(input.MethodBase.ToString())
{
HandleItSomeHow();
}
// process the call...
return getNext().Invoke(input, getNext);
}