如何从控件中删除所有事件处理程序

要在控件上创build新的事件处理程序,可以这样做

c.Click += new EventHandler(mainFormButton_Click); 

或这个

 c.Click += mainFormButton_Click; 

并删除一个事件处理程序,你可以做到这一点

 c.Click -= mainFormButton_Click; 

但是,如何从控件中删除所有事件处理程序?

我在MSDN论坛上find了一个解决scheme。 下面的示例代码将删除button1中的所有Click事件。

 public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += button1_Click; button1.Click += button1_Click2; button2.Click += button2_Click; } private void button1_Click(object sender, EventArgs e) { MessageBox.Show("Hello"); } private void button1_Click2(object sender, EventArgs e) { MessageBox.Show("World"); } private void button2_Click(object sender, EventArgs e) { RemoveClickEvent(button1); } 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]); } } } 

你们这样做太难了。 这很简单:

 void OnFormClosing(object sender, FormClosingEventArgs e) { foreach(Delegate d in FindClicked.GetInvocationList()) { FindClicked -= (FindClickedHandler)d; } } 

删除所有事件处理程序

直接没有,很大一部分是因为你不能简单的将事件设置为null。

间接地,您可以将实际事件设为私有,并在其周围创build一个跟踪所有正在被添加/删除的委托的属性。

采取以下措施:

 List<EventHandler> delegates = new List<EventHandler>(); private event EventHandler MyRealEvent; public event EventHandler MyEvent { add { MyRealEvent += value; delegates.Add(value); } remove { MyRealEvent -= value; delegates.Remove(value); } } public void RemoveAllEvents() { foreach(EventHandler eh in delegates) { MyRealEvent -= eh; } delegates.Clear(); } 

接受的答案未满。 它不适用于声明为{add; 去掉;}

这是工作代码:

 public static void ClearEventInvocations(this object obj, string eventName) { var fi = obj.GetType().GetEventField(eventName); if (fi == null) return; fi.SetValue(obj, null); } private static FieldInfo GetEventField(this Type type, string eventName) { FieldInfo field = null; while (type != null) { /* Find events defined as field */ field = type.GetField(eventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic); if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate)))) break; /* Find events defined as property { add; remove; } */ field = type.GetField("EVENT_" + eventName.ToUpper(), BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) break; type = type.BaseType; } return field; } 

删除一个不存在的事件处理程序并没有什么坏处。 所以,如果你知道可能有什么处理程序,你可以简单地删除所有的处理程序。 我只是有类似的情况。 这可能有助于在某些情况下。

喜欢:

 // Add handlers... if (something) { c.Click += DoesSomething; } else { c.Click += DoesSomethingElse; } // Remove handlers... c.Click -= DoesSomething; c.Click -= DoesSomethingElse; 

我实际上使用这种方法,它完美的作品。 我在这里被Aeonhack写的代码“启发”了。

 Public Event MyEvent() Protected Overrides Sub Dispose(ByVal disposing As Boolean) If MyEventEvent IsNot Nothing Then For Each d In MyEventEvent.GetInvocationList ' If this throws an exception, try using .ToArray RemoveHandler MyEvent, d Next End If End Sub 

MyEventEvent字段是隐藏的,但它确实存在。

debugging,你可以看到d.target是如何处理事件的,而d.method它的方法。 你只需要删除它。

它工作很好。 由于事件处理程序,没有更多的对象不被GC调用。

斯蒂芬有权利。 这很容易:

 public event EventHandler<Cles_graph_doivent_etre_redessines> les_graph_doivent_etre_redessines; public void remove_event() { if (this.les_graph_doivent_etre_redessines != null) { foreach (EventHandler<Cles_graph_doivent_etre_redessines> F_les_graph_doivent_etre_redessines in this.les_graph_doivent_etre_redessines.GetInvocationList()) { this.les_graph_doivent_etre_redessines -= F_les_graph_doivent_etre_redessines; } } } 

如果你不得不这样做,这将需要反思和相当一段时间来做到这一点。 事件处理程序在控件内的事件到委托映射中进行pipe理。 你需要

  • 在控件实例中反映并获取此映射。
  • 迭代每个事件,得到委托
    • 每个代表反过来可能是一连串的事件处理程序。 所以调用obControl.RemoveHandler(event,handler)

总之,很多工作。 这在理论上是可能的…我从来没有尝试过这样的事情。

看看你是否可以在控制的订阅 – 取消订阅阶段有更好的控制/纪律。

我刚刚发现如何暂停事件设置WinForms控件的属性 。 它将从控件中删除所有事件:

 namespace CMessWin05 { public class EventSuppressor { Control _source; EventHandlerList _sourceEventHandlerList; FieldInfo _headFI; Dictionary<object, Delegate[]> _handlers; PropertyInfo _sourceEventsInfo; Type _eventHandlerListType; Type _sourceType; public EventSuppressor(Control control) { if (control == null) throw new ArgumentNullException("control", "An instance of a control must be provided."); _source = control; _sourceType = _source.GetType(); _sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); _sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null); _eventHandlerListType = _sourceEventHandlerList.GetType(); _headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic); } private void BuildList() { _handlers = new Dictionary<object, Delegate[]>(); object head = _headFI.GetValue(_sourceEventHandlerList); if (head != null) { Type listEntryType = head.GetType(); FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic); BuildListWalk(head, delegateFI, keyFI, nextFI); } } private void BuildListWalk(object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI) { if (entry != null) { Delegate dele = (Delegate)delegateFI.GetValue(entry); object key = keyFI.GetValue(entry); object next = nextFI.GetValue(entry); Delegate[] listeners = dele.GetInvocationList(); if(listeners != null && listeners.Length > 0) _handlers.Add(key, listeners); if (next != null) { BuildListWalk(next, delegateFI, keyFI, nextFI); } } } public void Resume() { if (_handlers == null) throw new ApplicationException("Events have not been suppressed."); foreach (KeyValuePair<object, Delegate[]> pair in _handlers) { for (int x = 0; x < pair.Value.Length; x++) _sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]); } _handlers = null; } public void Suppress() { if (_handlers != null) throw new ApplicationException("Events are already being suppressed."); BuildList(); foreach (KeyValuePair<object, Delegate[]> pair in _handlers) { for (int x = pair.Value.Length - 1; x >= 0; x--) _sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]); } } } } 

哇。 我find了这个解决scheme,但没有像我想要的那样工作。 但是这很好:

 EventHandlerList listaEventos; private void btnDetach_Click(object sender, EventArgs e) { listaEventos = DetachEvents(comboBox1); } private void btnAttach_Click(object sender, EventArgs e) { AttachEvents(comboBox1, listaEventos); } public EventHandlerList DetachEvents(Component obj) { object objNew = obj.GetType().GetConstructor(new Type[] { }).Invoke(new object[] { }); PropertyInfo propEvents = obj.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList eventHandlerList_obj = (EventHandlerList)propEvents.GetValue(obj, null); EventHandlerList eventHandlerList_objNew = (EventHandlerList)propEvents.GetValue(objNew, null); eventHandlerList_objNew.AddHandlers(eventHandlerList_obj); eventHandlerList_obj.Dispose(); return eventHandlerList_objNew; } public void AttachEvents(Component obj, EventHandlerList eventos) { PropertyInfo propEvents = obj.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList eventHandlerList_obj = (EventHandlerList)propEvents.GetValue(obj, null); eventHandlerList_obj.AddHandlers(eventos); } 

我恨这里显示的任何完整的解决scheme,我现在做了一个混合和testing,工作任何事件处理程序:

 public class MyMain() public void MyMethod() { AnotherClass.TheEventHandler += DoSomeThing; } private void DoSomething(object sender, EventArgs e) { Debug.WriteLine("I did something"); AnotherClass.ClearAllDelegatesOfTheEventHandler(); } } public static class AnotherClass { public static event EventHandler TheEventHandler; public static void ClearAllDelegatesOfTheEventHandler() { foreach (Delegate d in TheEventHandler.GetInvocationList()) { TheEventHandler -= (EventHandler)d; } } } 

简单! 感谢Stephen Punak。

我使用它,因为我使用通用的本地方法来删除委托和本地方法调用不同的情况下,当不同的代表设置。

有时我们必须使用ThirdParty控件,我们需要构build这些尴尬的解决scheme。 基于@Anoop Muraleedharan答案我创build了这个推理types和ToolStripItem支持的解决scheme

  public static void RemoveItemEvents<T>(this T target, string eventName) where T : ToolStripItem { RemoveObjectEvents<T>(target, eventName); } public static void RemoveControlEvents<T>(this T target, string eventName) where T : Control { RemoveObjectEvents<T>(target, eventName); } private static void RemoveObjectEvents<T>(T target, string Event) where T : class { var typeOfT = typeof(T); var fieldInfo = typeOfT.BaseType.GetField( Event, BindingFlags.Static | BindingFlags.NonPublic); var provertyValue = fieldInfo.GetValue(target); var propertyInfo = typeOfT.GetProperty( "Events", BindingFlags.NonPublic | BindingFlags.Instance); var eventHandlerList = (EventHandlerList)propertyInfo.GetValue(target, null); eventHandlerList.RemoveHandler(provertyValue, eventHandlerList[provertyValue]); } 

你可以像这样使用它

  var toolStripButton = new ToolStripButton(); toolStripButton.RemoveItemEvents("EventClick"); var button = new Button(); button.RemoveControlEvents("EventClick"); 

那么,这里有另一个解决scheme来删除一个相关的事件(如果你已经有一个方法来处理控制事件):

 EventDescriptor ed = TypeDescriptor.GetEvents(this.button1).Find("MouseDown",true); Delegate delegate = Delegate.CreateDelegate(typeof(EventHandler), this, "button1_MouseDownClicked"); if(ed!=null) ed.RemoveEventHandler(this.button1, delegate); 

这不是OP的答案,但我想我会在这里发布这个以防万一它可以帮助别人。

  /// <summary> /// Method to remove a (single) SocketAsyncEventArgs.Completed event handler. This is /// partially based on information found here: http://stackoverflow.com/a/91853/253938 /// /// But note that this may not be a good idea, being very .Net implementation-dependent. Note /// in particular use of "m_Completed" instead of "Completed". /// </summary> private static void RemoveCompletedEventHandler(SocketAsyncEventArgs eventArgs) { FieldInfo fieldInfo = typeof(SocketAsyncEventArgs).GetField("m_Completed", BindingFlags.Instance | BindingFlags.NonPublic); eventArgs.Completed -= (EventHandler<SocketAsyncEventArgs>)fieldInfo.GetValue(eventArgs); } 

这个页面帮了我很多。 我从这里得到的代码是为了从button中删除点击事件。 我需要从某些面板中删除双击事件,并单击某些button上的事件。 所以我做了一个控件扩展,它将删除某个事件的所有事件处理程序。

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Reflection; public static class EventExtension { public static void RemoveEvents<T>(this Control target,string Event) { FieldInfo f1 = typeof(Control).GetField(Event,BindingFlags.Static | BindingFlags.NonPublic); object obj = f1.GetValue(target.CastTo<T>()); PropertyInfo pi = target.CastTo<T>().GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList list = (EventHandlerList)pi.GetValue(target.CastTo<T>(), null); list.RemoveHandler(obj, list[obj]); } } 

现在,这个扩展的用法。 如果您需要从button中删除点击事件,

 Button button = new Button(); button.RemoveEvents<Button>("EventClick"); 

如果您需要从面板中删除双击事件,

 Panel panel = new Panel(); panel.RemoveEvents<Panel>("EventDoubleClick"); 

我不是C#的专家,所以如果有任何错误,请原谅我,并请让我知道。

我发现这个答案,它几乎符合我的需求。 感谢SwDevMan81的课程。 我已经修改它允许压制和resumation个别方法,我想我会在这里发布。

 // This class allows you to selectively suppress event handlers for controls. You instantiate // the suppressor object with the control, and after that you can use it to suppress all events // or a single event. If you try to suppress an event which has already been suppressed // it will be ignored. Same with resuming; you can resume all events which were suppressed, // or a single one. If you try to resume an un-suppressed event handler, it will be ignored. //cEventSuppressor _supButton1 = null; //private cEventSuppressor SupButton1 { // get { // if (_supButton1 == null) { // _supButton1 = new cEventSuppressor(this.button1); // } // return _supButton1; // } //} //private void button1_Click(object sender, EventArgs e) { // MessageBox.Show("Clicked!"); //} //private void button2_Click(object sender, EventArgs e) { // SupButton1.Suppress("button1_Click"); //} //private void button3_Click(object sender, EventArgs e) { // SupButton1.Resume("button1_Click"); //} using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Windows.Forms; using System.ComponentModel; namespace Crystal.Utilities { public class cEventSuppressor { Control _source; EventHandlerList _sourceEventHandlerList; FieldInfo _headFI; Dictionary<object, Delegate[]> suppressedHandlers = new Dictionary<object, Delegate[]>(); PropertyInfo _sourceEventsInfo; Type _eventHandlerListType; Type _sourceType; public cEventSuppressor(Control control) { if (control == null) throw new ArgumentNullException("control", "An instance of a control must be provided."); _source = control; _sourceType = _source.GetType(); _sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); _sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null); _eventHandlerListType = _sourceEventHandlerList.GetType(); _headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic); } private Dictionary<object, Delegate[]> BuildList() { Dictionary<object, Delegate[]> retval = new Dictionary<object, Delegate[]>(); object head = _headFI.GetValue(_sourceEventHandlerList); if (head != null) { Type listEntryType = head.GetType(); FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic); retval = BuildListWalk(retval, head, delegateFI, keyFI, nextFI); } return retval; } private Dictionary<object, Delegate[]> BuildListWalk(Dictionary<object, Delegate[]> dict, object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI) { if (entry != null) { Delegate dele = (Delegate)delegateFI.GetValue(entry); object key = keyFI.GetValue(entry); object next = nextFI.GetValue(entry); if (dele != null) { Delegate[] listeners = dele.GetInvocationList(); if (listeners != null && listeners.Length > 0) { dict.Add(key, listeners); } } if (next != null) { dict = BuildListWalk(dict, next, delegateFI, keyFI, nextFI); } } return dict; } public void Resume() { } public void Resume(string pMethodName) { //if (_handlers == null) // throw new ApplicationException("Events have not been suppressed."); Dictionary<object, Delegate[]> toRemove = new Dictionary<object, Delegate[]>(); // goes through all handlers which have been suppressed. If we are resuming, // all handlers, or if we find the matching handler, add it back to the // control's event handlers foreach (KeyValuePair<object, Delegate[]> pair in suppressedHandlers) { for (int x = 0; x < pair.Value.Length; x++) { string methodName = pair.Value[x].Method.Name; if (pMethodName == null || methodName.Equals(pMethodName)) { _sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]); toRemove.Add(pair.Key, pair.Value); } } } // remove all un-suppressed handlers from the list of suppressed handlers foreach (KeyValuePair<object, Delegate[]> pair in toRemove) { for (int x = 0; x < pair.Value.Length; x++) { suppressedHandlers.Remove(pair.Key); } } //_handlers = null; } public void Suppress() { Suppress(null); } public void Suppress(string pMethodName) { //if (_handlers != null) // throw new ApplicationException("Events are already being suppressed."); Dictionary<object, Delegate[]> dict = BuildList(); foreach (KeyValuePair<object, Delegate[]> pair in dict) { for (int x = pair.Value.Length - 1; x >= 0; x--) { //MethodInfo mi = pair.Value[x].Method; //string s1 = mi.Name; // name of the method //object o = pair.Value[x].Target; // can use this to invoke method pair.Value[x].DynamicInvoke string methodName = pair.Value[x].Method.Name; if (pMethodName == null || methodName.Equals(pMethodName)) { _sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]); suppressedHandlers.Add(pair.Key, pair.Value); } } } } } }