要在控件上创建新的事件处理程序,可以这样做
c.Click += new EventHandler(mainFormButton_Click);
或者这个
c.Click += mainFormButton_Click;
要删除事件处理程序,可以这样做
c.Click -= mainFormButton_Click;
但是如何从事件中删除所有事件处理程序呢?
要在控件上创建新的事件处理程序,可以这样做
c.Click += new EventHandler(mainFormButton_Click);
或者这个
c.Click += mainFormButton_Click;
要删除事件处理程序,可以这样做
c.Click -= mainFormButton_Click;
但是如何从事件中删除所有事件处理程序呢?
当前回答
我讨厌这里展示的任何完整的解决方案,我现在做了一个混合和测试,为任何事件处理程序工作:
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。
我使用它是因为我使用一个通用的本地方法来删除委托,当设置不同的委托时,在不同的情况下调用本地方法。
其他回答
虽然有点晚了,但我使用了这个对我来说非常有效的链接: 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");
哇。我找到了这个解决方案,但没有一个像我想要的那样有效。但这个太好了:
EventHandlerList listaEventos;
private void btnDetach_Click(object sender, EventArgs e)
{
listaEventos = DetachEvents(comboBox1);
}
private void btnAttach_Click(object sender, EventArgs e)
{
AttachEvents(comboBox1, listaEventos);
}
public EventHandlerList DetachEvents(Component obj)
{
object objNew = obj.GetType().GetConstructor(new Type[] { }).Invoke(new object[] { });
PropertyInfo propEvents = obj.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList eventHandlerList_obj = (EventHandlerList)propEvents.GetValue(obj, null);
EventHandlerList eventHandlerList_objNew = (EventHandlerList)propEvents.GetValue(objNew, null);
eventHandlerList_objNew.AddHandlers(eventHandlerList_obj);
eventHandlerList_obj.Dispose();
return eventHandlerList_objNew;
}
public void AttachEvents(Component obj, EventHandlerList eventos)
{
PropertyInfo propEvents = obj.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList eventHandlerList_obj = (EventHandlerList)propEvents.GetValue(obj, null);
eventHandlerList_obj.AddHandlers(eventos);
}
从删除所有事件处理程序:
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(); }
你们对自己太苛刻了。很简单:
void OnFormClosing(object sender, FormClosingEventArgs e)
{
foreach(Delegate d in FindClicked.GetInvocationList())
{
FindClicked -= (FindClickedHandler)d;
}
}
这个页面对我帮助很大。我从这里得到的代码是为了从按钮中删除单击事件。我需要删除双击事件从一些面板和单击事件从一些按钮。所以我做了一个控件扩展,它将删除某个事件的所有事件处理程序。
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#方面的专家,所以如果有任何错误,请原谅我,并让我知道。