要在控件上创建新的事件处理程序,可以这样做
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");
其他回答
删除按钮的所有处理程序: save.RemoveEvents ();
public static class EventExtension
{
public static void RemoveEvents<T>(this T target) where T : Control
{
var propInfo = typeof(T).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
var list = (EventHandlerList)propInfo.GetValue(target, null);
list.Dispose();
}
}
这不是对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);
}
我在MSDN论坛上找到了一个解决方案。下面的示例代码将删除button1中的所有Click事件。
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]);
}
}
如果你真的要这么做……这需要深思熟虑和相当长的时间。事件处理程序在控件内的事件委托映射中进行管理。你需要
在控件实例中反射并获取此映射。 迭代每个事件,获取委托 每个委托可以依次是一系列链接的事件处理程序。调用obControl。RemoveHandler(事件处理程序)
简而言之,工作量很大。在理论上是可能的。我从没试过这样的东西。
看看是否可以对订阅-退订阶段有更好的控制/纪律。
你们对自己太苛刻了。很简单:
void OnFormClosing(object sender, FormClosingEventArgs e)
{
foreach(Delegate d in FindClicked.GetInvocationList())
{
FindClicked -= (FindClickedHandler)d;
}
}