441 Stimmen

So entfernen Sie alle Ereignisbehandler aus einem Ereignis

Um einen neuen Ereignishandler für ein Steuerelement zu erstellen, können Sie wie folgt vorgehen

c.Click += new EventHandler(mainFormButton_Click);

oder dies

c.Click += mainFormButton_Click;

und um einen Event-Handler zu entfernen, können Sie Folgendes tun

c.Click -= mainFormButton_Click;

Aber wie entfernt man alle Ereignisbehandler aus einem Ereignis?

21voto

Ich hasste alle hier gezeigten Komplettlösungen, ich habe einen Mix gemacht und jetzt getestet, funktioniert für jeden Eventhandler:

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

Vorsicht! Danke für Stephen Punak.

Ich habe es verwendet, weil ich eine generische lokale Methode zum Entfernen der Delegierten verwende und die lokale Methode nach verschiedenen Fällen aufgerufen wurde, wenn verschiedene Delegierte gesetzt sind.

16voto

Ivan Ferrer Villa Punkte 2030

Ich verwende diese Methode und sie funktioniert perfekt. Ich wurde von dem von Aeonhack geschriebenen Code "inspiriert". aquí .

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

Das Feld MeinEreignisEreignis ist ausgeblendet, aber es ist vorhanden.

Debugging, können Sie sehen, wie d.target ist das Objekt, das das Ereignis tatsächlich behandelt, und d.method seine Methode. Sie müssen sie nur entfernen.

Es funktioniert großartig. Keine Objekte mehr nicht GC'ed wegen der Event-Handler.

4voto

Gishu Punkte 130442

Wenn Sie wirklich Ich muss das tun... es braucht Nachdenken und viel Zeit, um das zu tun. Event-Handler werden in einer Event-to-Delegate-Map innerhalb eines Steuerelements verwaltet. Sie müssen

  • Reflektieren Sie und erhalten Sie diese Karte in der Kontrollinstanz.
  • Iterieren für jedes Ereignis, um den Delegierten zu erhalten
    • jeder Delegat könnte wiederum eine verkettete Reihe von Ereignisbehandlern sein. Also obControl.RemoveHandler(event, handler) aufrufen

Kurz gesagt, eine Menge Arbeit. Theoretisch ist es möglich... Ich habe so etwas nie ausprobiert.

Versuchen Sie, die An- und Abmeldephase besser zu kontrollieren und zu disziplinieren.

3voto

SwDevMan81 Punkte 47339

Ich habe gerade gefunden Wie man Ereignisse beim Setzen einer Eigenschaft eines WinForms-Steuerelements aussetzen kann . Es werden alle Ereignisse aus einem Steuerelement entfernt:

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

    }
}

2voto

mmike Punkte 45

Stephen hat Recht. Es ist sehr einfach:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X