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

c.Click += new EventHandler(mainFormButton_Click);

或者这个

c.Click += mainFormButton_Click;

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

c.Click -= mainFormButton_Click;

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


当前回答

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

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

现在,这个扩展的用法。 如果需要从按钮中删除单击事件,

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

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

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

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

其他回答

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

有时我们不得不使用第三方控件,我们需要构建这些尴尬的解决方案。基于@Anoop Muraleedharan的答案,我创建了这个具有推理类型和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]);
    }

你可以这样使用它

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

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

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

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。

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

删除按钮的所有处理程序: save.RemoveEvents ();

public static class EventExtension
{
    public static void RemoveEvents<T>(this T target) where T : Control
    {
       var propInfo = typeof(T).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
        var list = (EventHandlerList)propInfo.GetValue(target, null);
        list.Dispose();
    }
}

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

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

现在,这个扩展的用法。 如果需要从按钮中删除单击事件,

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

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

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

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