7

Possible Duplicate: How would that be possible to remove all event handlers of the Click event of a Button?

I want to remove all click event handlers from a button. I found this method in Stack Overflow question How to remove all event handlers from a control.

private void RemoveClickEvent(Button b)
{
    FieldInfo f1 = typeof(Control).GetField("EventClick",
                                            BindingFlags.Static |
                                            BindingFlags.NonPublic);
    object obj = f1.GetValue(b);
    PropertyInfo pi = b.GetType().GetProperty("Events",
                                              BindingFlags.NonPublic |
                                              BindingFlags.Instance);
    EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
    list.RemoveHandler(obj, list[obj]);
}

But this line always returns null:

  typeof(Control).GetField("EventClick", BindingFlags.Static | BindingFlags.NonPublic);

And this method was written in 2006.

Is there any latest version of this method?

Note: I am working with WPF and .NET 4.0.

4
  • I can't help much for why that's returning null, but @JonSkeet has a pretty good answer at stackoverflow.com/questions/6828054/… on why this is not possible without reflection. Perhaps you need to approach the problem differently. Commented Feb 24, 2012 at 17:07
  • 1
    What is the fundamental problem you're trying to solve / goal you're trying to accomplish? Commented Feb 24, 2012 at 17:53
  • You realize that you’re trying to apply WinForms code to WPF? Commented Feb 24, 2012 at 19:07
  • see answer "Solution to remove Event handler dynamically (using reflection). Is there a better way to do this?" stackoverflow.com/questions/11031149/… Commented Jun 14, 2012 at 10:24

1 Answer 1

20

The below is a helpful utility method for retrieving all subscribed event handlers for any routed event:

/// <summary>
/// Gets the list of routed event handlers subscribed to the specified routed event.
/// </summary>
/// <param name="element">The UI element on which the event is defined.</param>
/// <param name="routedEvent">The routed event for which to retrieve the event handlers.</param>
/// <returns>The list of subscribed routed event handlers.</returns>
public static RoutedEventHandlerInfo[] GetRoutedEventHandlers(UIElement element, RoutedEvent routedEvent)
{
    // Get the EventHandlersStore instance which holds event handlers for the specified element.
    // The EventHandlersStore class is declared as internal.
    var eventHandlersStoreProperty = typeof(UIElement).GetProperty(
        "EventHandlersStore", BindingFlags.Instance | BindingFlags.NonPublic);
    object eventHandlersStore = eventHandlersStoreProperty.GetValue(element, null);

    // Invoke the GetRoutedEventHandlers method on the EventHandlersStore instance 
    // for getting an array of the subscribed event handlers.
    var getRoutedEventHandlers = eventHandlersStore.GetType().GetMethod(
        "GetRoutedEventHandlers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    var routedEventHandlers = (RoutedEventHandlerInfo[])getRoutedEventHandlers.Invoke(
        eventHandlersStore, new object[] { routedEvent });

    return routedEventHandlers;
}

Using the above, the implementation of your method becomes quite simple:

private void RemoveClickEvent(Button b)
{
    var routedEventHandlers = GetRoutedEventHandlers(b, ButtonBase.ClickEvent);
    foreach (var routedEventHandler in routedEventHandlers)
        b.Click -= (RoutedEventHandler)routedEventHandler.Handler;
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is a very useful answer that is unfortunately attached to a closed question. I think the "duplicate" would be improved by you providing the same answer there as well.
@phloopy: Good suggestion. I just posted an improved version of the above solution there.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.