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

c.Click += new EventHandler(mainFormButton_Click);

或者这个

c.Click += mainFormButton_Click;

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

c.Click -= mainFormButton_Click;

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


当前回答

好吧,这里有另一个解决方案来删除关联事件(如果你已经有一个方法来处理控件的事件):

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

其他回答

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

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

实际上我在用这个方法,效果很好。我受到了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。

有时我们不得不使用第三方控件,我们需要构建这些尴尬的解决方案。基于@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");

删除按钮的所有处理程序: 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#方面的专家,所以如果有任何错误,请原谅我,并让我知道。