Как удалить все обработчики событий Click?

Возможный дубликат: Как можно удалить все обработчики событий события Click кнопки?

Я хочу удалить все обработчики событий кликов с одной кнопки. Я нашел этот метод в вопросе Как удалить все обработчики событий из элемента управления.

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

Но эта строка всегда возвращает null:

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

И этот метод был написан в 2006 году.

Есть ли последняя версия этого метода?

Примечание. Я работаю с WPF и .NET 4.0.

Ответ 1

Ниже приведен полезный метод утилиты для извлечения всех подписанных обработчиков событий для любого маршрутизируемого события:

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

Используя вышеизложенное, реализация вашего метода становится довольно простой:

private void RemoveClickEvent(Button b)
{
    var routedEventHandlers = GetRoutedEventHandlers(b, ButtonBase.ClickEvent);
    foreach (var routedEventHandler in routedEventHandlers)
        b.Click -= (RoutedEventHandler)routedEventHandler.Handler;
}