要在控件上创建新的事件处理程序,您可以执行此操作
c.Click += new EventHandler(mainFormButton_Click);
或这个
c.Click += mainFormButton_Click;
并删除事件处理程序,您可以执行此操作
c.Click -= mainFormButton_Click;
但是如何从事件中删除所有事件处理程序?
我在MSDN论坛上找到了一个解决方案.下面的示例代码将删除所有Click
事件button1
.
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]); } } }
你们这些方式对你们来说太过刻板了.就这么简单:
void OnFormClosing(object sender, FormClosingEventArgs e) { foreach(Delegate d in FindClicked.GetInvocationList()) { FindClicked -= (FindClickedHandler)d; } }
从删除所有事件处理程序:
直接不,很大程度上是因为你不能简单地将事件设置为null.
间接地,您可以将实际事件设为私有,并在其周围创建一个属性,跟踪所有被添加/减去的代理.
请考虑以下事项:
Listdelegates = new List (); 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(); }
接受的答案不完整.它不适用于声明为{add; 去掉;}
这是工作代码:
public static void ClearEventInvocations(this object obj, string eventName) { var fi = obj.GetType().GetEventField(eventName); if (fi == null) return; fi.SetValue(obj, null); } private static FieldInfo GetEventField(this Type type, string eventName) { FieldInfo field = null; while (type != null) { /* Find events defined as field */ field = type.GetField(eventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic); if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate)))) break; /* Find events defined as property { add; remove; } */ field = type.GetField("EVENT_" + eventName.ToUpper(), BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) break; type = type.BaseType; } return field; }
删除不存在的事件处理程序没有任何损害.因此,如果你知道可能有哪些处理程序,你可以简单地删除它们.我刚才有类似的情况.在某些情况下这可能有所帮助.
喜欢:
// Add handlers... if (something) { c.Click += DoesSomething; } else { c.Click += DoesSomethingElse; } // Remove handlers... c.Click -= DoesSomething; c.Click -= DoesSomethingElse;
我实际上正在使用这种方法,它完美无缺.我被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
MyEventEvent字段是隐藏的,但确实存在.
调试时,您可以看到d.target
对象实际上是如何处理事件的,以及d.method
它的方法.你只需要删除它.
它很棒.由于事件处理程序,没有更多的对象没有GC.
我讨厌这里显示的任何完整的解决方案,我做了混合并现在测试,适用于任何事件处理程序:
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.
我使用它是因为我使用通用的本地方法来删除委托,并且在设置不同的委托时,在不同的情况下调用本地方法.
如果你真的必须这样做......它需要反思并且需要相当长的时间才能做到这一点.事件处理程序在控件内的事件到委托映射中进行管理.你需要
在控件实例中反映并获取此映射.
迭代每个事件,获得代表
每个代表反过来可以是一系列链式事件处理程序.所以调用obControl.RemoveHandler(event,handler)
总之,做了很多工作.这在理论上是可能的......我从来没有尝试过这样的事情.
看看你是否可以在控件的subscribe-unsubscribe阶段有更好的控制/纪律.