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

c.Click += new EventHandler(mainFormButton_Click);

或者这个

c.Click += mainFormButton_Click;

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

c.Click -= mainFormButton_Click;

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


当前回答

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

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(事件处理程序)

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

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

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

虽然有点晚了,但我使用了这个对我来说非常有效的链接: https://www.codeproject.com/Articles/103542/Removing-Event-Handlers-using-Reflection

这个代码的美妙之处在于它适用于所有人,WFP, Forms, Xamarin Forms。我用它来做沙玛林。请注意,只有当你不拥有这个事件(例如,一个库代码在你不关心的一些事件上崩溃)时,你才需要这种方式使用Reflection。

下面是我稍微修改过的代码:

    static Dictionary<Type, List<FieldInfo>> dicEventFieldInfos = new Dictionary<Type, List<FieldInfo>>();

    static BindingFlags AllBindings
    {
        get { return BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; }
    }

    static void BuildEventFields(Type t, List<FieldInfo> lst)
    {
        foreach (EventInfo ei in t.GetEvents(AllBindings))
        {
            Type dt = ei.DeclaringType;
            FieldInfo fi = dt.GetField(ei.Name, AllBindings);
            if (fi != null)
                lst.Add(fi);
        }
    }
    static List<FieldInfo> GetTypeEventFields(Type t)
    {
        if (dicEventFieldInfos.ContainsKey(t))
            return dicEventFieldInfos[t];

        List<FieldInfo> lst = new List<FieldInfo>();
        BuildEventFields(t, lst);
        dicEventFieldInfos.Add(t, lst);
        return lst;
    }
    static EventHandlerList GetStaticEventHandlerList(Type t, object obj)
    {
        MethodInfo mi = t.GetMethod("get_Events", AllBindings);
        return (EventHandlerList)mi.Invoke(obj, new object[] { });
    }
    public static void RemoveEventHandler(object obj, string EventName = "")
    {
        if (obj == null)
            return;

        Type t = obj.GetType();
        List<FieldInfo> event_fields = GetTypeEventFields(t);
        EventHandlerList static_event_handlers = null;

        foreach (FieldInfo fi in event_fields)
        {
            if (EventName != "" && string.Compare(EventName, fi.Name, true) != 0)
                continue;
            var eventName = fi.Name;
            // After hours and hours of research and trial and error, it turns out that
            // STATIC Events have to be treated differently from INSTANCE Events...
            if (fi.IsStatic)
            {
                // STATIC EVENT
                if (static_event_handlers == null)
                    static_event_handlers = GetStaticEventHandlerList(t, obj);

                object idx = fi.GetValue(obj);
                Delegate eh = static_event_handlers[idx];
                if (eh == null)
                    continue;

                Delegate[] dels = eh.GetInvocationList();
                if (dels == null)
                    continue;

                EventInfo ei = t.GetEvent(eventName, AllBindings);
                foreach (Delegate del in dels)
                    ei.RemoveEventHandler(obj, del);
            }
            else
            {
                // INSTANCE EVENT
                EventInfo ei = t.GetEvent(eventName, AllBindings);
                if (ei != null)
                {
                    object val = fi.GetValue(obj);
                    Delegate mdel = (val as Delegate);
                    if (mdel != null)
                    {
                        foreach (Delegate del in mdel.GetInvocationList())
                        {
                            ei.RemoveEventHandler(obj, del);
                        }
                    }
                }
            }
        }
    }


示例用法:RemoveEventHandler(obj, "Focused");

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

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

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

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