要在控件上创建新的事件处理程序,您可以执行此操作
c.Click += new EventHandler(mainFormButton_Click);
Run Code Online (Sandbox Code Playgroud)
或这个
c.Click += mainFormButton_Click;
Run Code Online (Sandbox Code Playgroud)
并删除事件处理程序,您可以执行此操作
c.Click -= mainFormButton_Click;
Run Code Online (Sandbox Code Playgroud)
但是如何从事件中删除所有事件处理程序?
xsl*_*xsl 164
我在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]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 138
你们这些方式对你们来说太过刻板了.就这么简单:
void OnFormClosing(object sender, FormClosingEventArgs e)
{
foreach(Delegate d in FindClicked.GetInvocationList())
{
FindClicked -= (FindClickedHandler)d;
}
}
Run Code Online (Sandbox Code Playgroud)
Jor*_*ira 73
直接不,很大程度上是因为你不能简单地将事件设置为null.
间接地,您可以将实际事件设为私有,并在其周围创建一个属性,跟踪所有被添加/减去的代理.
请考虑以下事项:
Run Code Online (Sandbox Code Playgroud)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(); }
Lio*_*oft 60
接受的答案不完整.它不适用于声明为{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;
}
Run Code Online (Sandbox Code Playgroud)
小智 39
删除不存在的事件处理程序没有任何损害.因此,如果你知道可能有哪些处理程序,你可以简单地删除它们.我刚才有类似的情况.在某些情况下这可能有所帮助.
喜欢:
// Add handlers...
if (something)
{
c.Click += DoesSomething;
}
else
{
c.Click += DoesSomethingElse;
}
// Remove handlers...
c.Click -= DoesSomething;
c.Click -= DoesSomethingElse;
Run Code Online (Sandbox Code Playgroud)
Iva*_*lla 17
我实际上正在使用这种方法,它完美无缺.我被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
Run Code Online (Sandbox Code Playgroud)
MyEventEvent字段是隐藏的,但确实存在.
调试时,您可以看到d.target对象实际上是如何处理事件的,以及d.method它的方法.你只需要删除它.
它很棒.由于事件处理程序,没有更多的对象没有GC.
小智 9
我讨厌这里显示的任何完整的解决方案,我做了混合并现在测试,适用于任何事件处理程序:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
简单!谢谢Stephen Punak.
我使用它是因为我使用通用的本地方法来删除委托,并且在设置不同的委托时,在不同的情况下调用本地方法.
如果你真的必须这样做......它需要反思并且需要相当长的时间才能做到这一点.事件处理程序在控件内的事件到委托映射中进行管理.你需要
总之,做了很多工作.这在理论上是可能的......我从来没有尝试过这样的事情.
看看你是否可以在控件的subscribe-unsubscribe阶段有更好的控制/纪律.
| 归档时间: |
|
| 查看次数: |
390334 次 |
| 最近记录: |