Getting all the attached event handlers for a WPF control - c#

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.

Related

How to know if event was attached in run time

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.

Is there anyway to stop the flow of events in .NET?

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.

Getting KeyCode in GotFocus event?

C# WinApps: Is there any way that I can check if something like CTRL-V is pressed but not in the KeyDown,PreviewKeyDown,KeyPress,etc ... events? those are being eaten by some other parts in my App and it is so hard to find them so I thought Ok for this contorl lets check the pressed keys in its GotFocus event! Is it possible?
Not sure what you mean by the events being "eaten". Events can call multiple handlers. So even if the event is already being subscribed to by one handler, you can subscribe to it with another handler and it should work just fine.
Another option would be to subclass the control you are using and use the subclass instead. Then you can override the On{event} methods and do anything you want with those (be sure to call the base method as well to ensure the behavior of the original class is still in place).
HTH

Events Firing Unexpectedly

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.

C#: Create an event that is fired whenever another event that has listeners is fired, dynamically via reflection maybe?

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);
}

Categories