要在控件上创建新的事件处理程序,可以这样做
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;
但是如何从事件中删除所有事件处理程序呢?
当前回答
有时我们不得不使用第三方控件,我们需要构建这些尴尬的解决方案。基于@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");
其他回答
好吧,这里有另一个解决方案来删除关联事件(如果你已经有一个方法来处理控件的事件):
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);
这不是对OP的回答,但我想我把它贴在这里,以防它能帮助到其他人。
/// <summary>
/// Method to remove a (single) SocketAsyncEventArgs.Completed event handler. This is
/// partially based on information found here: http://stackoverflow.com/a/91853/253938
///
/// But note that this may not be a good idea, being very .Net implementation-dependent. Note
/// in particular use of "m_Completed" instead of "Completed".
/// </summary>
private static void RemoveCompletedEventHandler(SocketAsyncEventArgs eventArgs)
{
FieldInfo fieldInfo = typeof(SocketAsyncEventArgs).GetField("m_Completed",
BindingFlags.Instance | BindingFlags.NonPublic);
eventArgs.Completed -= (EventHandler<SocketAsyncEventArgs>)fieldInfo.GetValue(eventArgs);
}
这个页面对我帮助很大。我从这里得到的代码是为了从按钮中删除单击事件。我需要删除双击事件从一些面板和单击事件从一些按钮。所以我做了一个控件扩展,它将删除某个事件的所有事件处理程序。
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#方面的专家,所以如果有任何错误,请原谅我,并让我知道。
我讨厌这里展示的任何完整的解决方案,我现在做了一个混合和测试,为任何事件处理程序工作:
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。
我使用它是因为我使用一个通用的本地方法来删除委托,当设置不同的委托时,在不同的情况下调用本地方法。
接受的答案不完整。对于声明为{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;
}