otro lista instanciar eventos evento ejecutar disparar deshabilitar desde boton activar c# .net events

lista - instanciar un evento c#



Cómo eliminar todos los controladores de eventos de un evento (16)

A veces tenemos que trabajar con los controles de ThirdParty y tenemos que crear estas soluciones incómodas. Basado en la respuesta de @Anoop Muraleedharan, creé esta solución con tipo de inferencia y soporte ToolStripItem

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

Y puedes usarlo así.

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

Para crear un nuevo controlador de eventos en un control, puede hacer esto

c.Click += new EventHandler(mainFormButton_Click);

o esto

c.Click += mainFormButton_Click;

y para eliminar un controlador de eventos puede hacer esto

c.Click -= mainFormButton_Click;

Pero, ¿cómo se eliminan todos los controladores de eventos de un evento?


Acabo de encontrar Cómo suspender eventos al configurar una propiedad de un control WinForms . Se eliminarán todos los eventos de un control:

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


Bueno, aquí hay otra solución para eliminar un evento asociado (si ya tiene un método para manejar los eventos para el control):

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


De eliminar todos los controladores de eventos :

Directamente no, en gran parte porque simplemente no puede establecer el evento en nulo.

Indirectamente, puede hacer que el evento real sea privado y crear una propiedad a su alrededor que haga un seguimiento de todos los delegados que se agregan / restan.

Toma lo siguiente:

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


En realidad estoy usando este método y funciona perfectamente. Me inspiré en el código escrito por Aeonhack here .

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

El campo MyEventEvent está oculto, pero existe.

Al depurar, puede ver cómo d.target es el objeto que realmente maneja el evento y d.method su método. Solo tienes que quitarlo.

Funciona muy bien No hay más objetos que no sean GC''ed debido a los controladores de eventos.


Encontré esta respuesta y casi se ajusta a mis necesidades. Gracias a SwDevMan81 por la clase. Lo he modificado para permitir la supresión y la reanudación de métodos individuales, y pensé que lo publicaría aquí.

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


Encontré una solución en los foros de MSDN . El código de ejemplo a continuación eliminará todos los eventos Click del button1 .

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


Esta no es una respuesta para el OP, pero pensé que publicaría esto aquí en caso de que pueda ayudar a otros.

/// <summary> /// Method to remove a (single) SocketAsyncEventArgs.Completed event handler. This is /// partially based on information found here: http://.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); }


Esta página me ayudó mucho. El código que obtuve de aquí estaba destinado a eliminar un evento de clic de un botón. Necesito eliminar eventos de doble clic de algunos paneles y hacer clic en eventos de algunos botones. Así que hice una extensión de control, que eliminará todos los controladores de eventos para un evento determinado.

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 T target, string eventName) where T:Control { if (ReferenceEquals(target, null)) throw new NullReferenceException("Argument /"target/" may not be null."); FieldInfo fieldInfo = typeof(Control).GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic); if (ReferenceEquals(fieldInfo, null)) throw new ArgumentException( string.Concat("The control ", typeof(T).Name, " does not have a property with the name /"", eventName, "/""), nameof(eventName)); object eventInstance = fieldInfo.GetValue(target); PropertyInfo propInfo = typeof(T).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList list = (EventHandlerList)propInfo.GetValue(target, null); list.RemoveHandler(eventInstance, list[eventInstance]); } }

Ahora, el uso de este extenstion. Si necesita eliminar los eventos de clic de un botón,

Button button = new Button(); button.RemoveEvents(nameof(button.EventClick));

Si necesita eliminar los eventos de doble clic de un panel,

Panel panel = new Panel(); panel.RemoveEvents(nameof(panel.EventDoubleClick));

No soy un experto en C #, así que si hay algún error, por favor, perdóname y por favor avísame.


Guau. Encontré esta solución, pero nada funcionó como yo quería. Pero esto es tan bueno:

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


La respuesta aceptada no está completa. No funciona para eventos declarados como {agregar; retirar;}

Aquí está el código de trabajo:

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


No hace ningún daño eliminar un controlador de eventos que no existe. Entonces, si sabe qué controladores pueden existir, simplemente puede eliminarlos todos. Acabo de tener un caso similar. Esto puede ayudar en algunos casos.

Me gusta:

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


Odiaba las soluciones completas que se muestran aquí, hice una mezcla y probé ahora, funcionó para cualquier controlador de eventos:

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

¡Fácil! Gracias por Stephen Punak.

Lo usé porque uso un método local genérico para eliminar a los delegados y se llamó al método local después de diferentes casos, cuando se establecieron diferentes delegados.


Si realmente tienes que hacer esto ... tardarás en reflexionar y bastante tiempo en hacerlo. Los controladores de eventos se administran en un mapa de evento a delegado dentro de un control. Necesitarías

  • Reflexione y obtenga este mapa en la instancia de control.
  • Iterar para cada evento, obtener el delegado.
    • cada delegado a su vez podría ser una serie encadenada de controladores de eventos. Así que llame a obControl.RemoveHandler (event, handler)

En definitiva, mucho trabajo. Es posible en teoría ... Nunca intenté algo como esto.

Vea si puede tener mejor control / disciplina en la fase de suscripción-cancelación de la suscripción para el control.


Stephen tiene razón. Es muy fácil:

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


Ustedes están haciendo esto demasiado duro para ustedes mismos. Es así de fácil:

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