How would it be possible to remove all event handlers of the ‘Click’ event of a ‘Button’?

Note: Since the question on which I posted my original answer was closed as a duplicate of this question, I’m cross-posting an improved version of my answer here. This answer only applies to WPF. It will not work on Windows Forms or any other UI framework.

The below is a helpful utility method for removing all event handlers subscribed to a routed event on a given element. You can trivially convert this to an extension method if you like.

/// <summary>
/// Removes all event handlers subscribed to the specified routed event from the specified element.
/// </summary>
/// <param name="element">The UI element on which the routed event is defined.</param>
/// <param name="routedEvent">The routed event for which to remove the event handlers.</param>
public static void RemoveRoutedEventHandlers(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);

    // If no event handlers are subscribed, eventHandlersStore will be null.
    // Credit: https://stackoverflow.com/a/16392387/1149773
    if (eventHandlersStore == null)
        return;

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

    // Iteratively remove all routed event handlers from the element.
    foreach (var routedEventHandler in routedEventHandlers)
        element.RemoveHandler(routedEvent, routedEventHandler.Handler);
}

You could then easily call this utility method for your button’s Click event:

RemoveRoutedEventHandlers(button, Button.ClickEvent);

Edit: I’ve copied the bug fix implemented by corona, which stops the method from throwing a NullReferenceException when no event handlers are subscribed. Credit (and upvotes) should go to their answer.

Leave a Comment