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

c.Click += new EventHandler(mainFormButton_Click);

或者这个

c.Click += mainFormButton_Click;

要删除事件处理程序,可以这样做

c.Click -= mainFormButton_Click;

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


当前回答

实际上我在用这个方法,效果很好。我受到了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
    ~MyClass()
    {
        if (MyEventEvent != null)
        {
            foreach (var d in MyEventEvent.GetInvocationList())
            {
                MyEventEvent -= (MyEvent)d;
            }
        }

    }

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

调试过程中,你可以看到d.t target是如何实际处理事件的对象,而d.m ode是如何处理事件的方法。你只需要把它拿掉。

效果很好。不再有对象因为事件处理程序而被GC。

其他回答

从删除所有事件处理程序:

Directly no, in large part because you cannot simply set the event to null. Indirectly, you could make the actual event private and create a property around it that tracks all of the delegates being added/subtracted to it. Take the following: 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(); }

如果你真的要这么做……这需要深思熟虑和相当长的时间。事件处理程序在控件内的事件委托映射中进行管理。你需要

在控件实例中反射并获取此映射。 迭代每个事件,获取委托 每个委托可以依次是一系列链接的事件处理程序。调用obControl。RemoveHandler(事件处理程序)

简而言之,工作量很大。在理论上是可能的。我从没试过这样的东西。

看看是否可以对订阅-退订阶段有更好的控制/纪律。

我讨厌这里展示的任何完整的解决方案,我现在做了一个混合和测试,为任何事件处理程序工作:

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。

我使用它是因为我使用一个通用的本地方法来删除委托,当设置不同的委托时,在不同的情况下调用本地方法。

我在MSDN论坛上找到了一个解决方案。下面的示例代码将删除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]);
    }
}

斯蒂芬是对的。这很简单:

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