2012-02-24 140 views
7

可能重複: How would that be possible to remove all event handlers of the Click event of a Button?如何刪除所有Click事件處理程序?

我想從一個按鈕,刪除所有的單擊事件處理程序。我在堆棧溢出問題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]); 
} 

,但此行總是返回null:

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

而且這種方法寫於2006年

是否有此方法的任何最新版本?

注意:我正在使用WPF.NET 4.0。

+0

我可以對於爲什麼返回空值沒有幫助,但@JonSkeet在http://stackoverflow.com/questions/6828054/how-would-that-be-possible-to-remove-all-event-handlers上有一個很好的答案。關於爲什麼不經過反思就無法實現這一點的事件。也許你需要以不同的方式解決問題。 – 2012-02-24 17:07:37

+1

你試圖解決的根本問題是什麼?你試圖完成的目標是什麼? – RQDQ 2012-02-24 17:53:21

+0

你意識到你正試圖將WinForms代碼應用於WPF? – Douglas 2012-02-24 19:07:27

回答

19

下面是用於檢索所有訂閱的事件處理程序的任何路由事件有幫助的實用方法:

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

這是一個非常有用的答案,不幸附加到一個封閉的問題。我認爲這個「重複」可以通過你在那裏提供相同的答案來改善。 – phloopy 2012-08-21 01:36:23

+1

@phloopy:很好的建議。我剛剛發佈了上述解決方案的[改進版本](http://stackoverflow.com/a/12618521/1149773)。 – Douglas 2012-09-27 09:48:05