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
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");
// This class allows you to selectively suppress event handlers for controls. You instantiate
// the suppressor object with the control, and after that you can use it to suppress all events
// or a single event. If you try to suppress an event which has already been suppressed
// it will be ignored. Same with resuming; you can resume all events which were suppressed,
// or a single one. If you try to resume an un-suppressed event handler, it will be ignored.
//cEventSuppressor _supButton1 = null;
//private cEventSuppressor SupButton1 {
// get {
// if (_supButton1 == null) {
// _supButton1 = new cEventSuppressor(this.button1);
// }
// return _supButton1;
// }
//}
//private void button1_Click(object sender, EventArgs e) {
// MessageBox.Show("Clicked!");
//}
//private void button2_Click(object sender, EventArgs e) {
// SupButton1.Suppress("button1_Click");
//}
//private void button3_Click(object sender, EventArgs e) {
// SupButton1.Resume("button1_Click");
//}
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.ComponentModel;
namespace Crystal.Utilities {
public class cEventSuppressor {
Control _source;
EventHandlerList _sourceEventHandlerList;
FieldInfo _headFI;
Dictionary<object, Delegate[]> suppressedHandlers = new Dictionary<object, Delegate[]>();
PropertyInfo _sourceEventsInfo;
Type _eventHandlerListType;
Type _sourceType;
public cEventSuppressor(Control control) {
if (control == null)
throw new ArgumentNullException("control", "An instance of a control must be provided.");
_source = control;
_sourceType = _source.GetType();
_sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
_sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null);
_eventHandlerListType = _sourceEventHandlerList.GetType();
_headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic);
}
private Dictionary<object, Delegate[]> BuildList() {
Dictionary<object, Delegate[]> retval = new Dictionary<object, Delegate[]>();
object head = _headFI.GetValue(_sourceEventHandlerList);
if (head != null) {
Type listEntryType = head.GetType();
FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic);
retval = BuildListWalk(retval, head, delegateFI, keyFI, nextFI);
}
return retval;
}
private Dictionary<object, Delegate[]> BuildListWalk(Dictionary<object, Delegate[]> dict,
object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI) {
if (entry != null) {
Delegate dele = (Delegate)delegateFI.GetValue(entry);
object key = keyFI.GetValue(entry);
object next = nextFI.GetValue(entry);
if (dele != null) {
Delegate[] listeners = dele.GetInvocationList();
if (listeners != null && listeners.Length > 0) {
dict.Add(key, listeners);
}
}
if (next != null) {
dict = BuildListWalk(dict, next, delegateFI, keyFI, nextFI);
}
}
return dict;
}
public void Resume() {
}
public void Resume(string pMethodName) {
//if (_handlers == null)
// throw new ApplicationException("Events have not been suppressed.");
Dictionary<object, Delegate[]> toRemove = new Dictionary<object, Delegate[]>();
// goes through all handlers which have been suppressed. If we are resuming,
// all handlers, or if we find the matching handler, add it back to the
// control's event handlers
foreach (KeyValuePair<object, Delegate[]> pair in suppressedHandlers) {
for (int x = 0; x < pair.Value.Length; x++) {
string methodName = pair.Value[x].Method.Name;
if (pMethodName == null || methodName.Equals(pMethodName)) {
_sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]);
toRemove.Add(pair.Key, pair.Value);
}
}
}
// remove all un-suppressed handlers from the list of suppressed handlers
foreach (KeyValuePair<object, Delegate[]> pair in toRemove) {
for (int x = 0; x < pair.Value.Length; x++) {
suppressedHandlers.Remove(pair.Key);
}
}
//_handlers = null;
}
public void Suppress() {
Suppress(null);
}
public void Suppress(string pMethodName) {
//if (_handlers != null)
// throw new ApplicationException("Events are already being suppressed.");
Dictionary<object, Delegate[]> dict = BuildList();
foreach (KeyValuePair<object, Delegate[]> pair in dict) {
for (int x = pair.Value.Length - 1; x >= 0; x--) {
//MethodInfo mi = pair.Value[x].Method;
//string s1 = mi.Name; // name of the method
//object o = pair.Value[x].Target;
// can use this to invoke method pair.Value[x].DynamicInvoke
string methodName = pair.Value[x].Method.Name;
if (pMethodName == null || methodName.Equals(pMethodName)) {
_sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]);
suppressedHandlers.Add(pair.Key, pair.Value);
}
}
}
}
}
}
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#的专家,所以如果有任何错误请原谅我,请让我知道 .
116
这不是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);
}
16 回答
我通过Aeonhack here编写的代码激发了我的灵感 .
MyEventEvent字段是隐藏的,但确实存在 .
调试时,您可以看到
d.target
是如何实际处理事件的对象,以及d.method
其方法 . 你只需要删除它 .它很棒 . 由于事件处理程序,没有更多的对象没有GC .
你们这些方式太过刻板了 . 就这么简单:
删除不存在的事件处理程序没有任何损害 . 因此,如果你知道可能有哪些处理程序,你可以简单地删除它们 . 我只是有类似的情况 . 在某些情况下这可能有所帮助 .
喜欢:
从Removing All Event Handlers:
私人活动EventHandler MyRealEvent;
公共事件EventHandler MyEvent
{
加
{
MyRealEvent = value;
delegates.Add(值);
}
去掉
{
MyRealEvent - =值;
delegates.Remove(值);
}
}
public void RemoveAllEvents()
{
foreach(EventHandler呃代表)
{
MyRealEvent - =呃;
}
delegates.Clear();
}
如果你必须这样做......它需要反思并且需要相当长的时间才能做到这一点 . 事件处理程序在控件内的事件到委托映射中进行管理 . 你需要
在控件实例中反映并获取此映射 .
为每个事件迭代,获得代表
每个代表反过来可以是一系列链式事件处理程序 . 所以调用obControl.RemoveHandler(event,handler)
总之,做了很多工作 . 理论上可能......我从未尝试过这样的事情 .
看看你是否可以在控件的subscribe-unsubscribe阶段有更好的控制/纪律 .
哇 . 我找到了这个解决方案,但没有像我想要的那样工作 . 但这太好了:
有时我们必须使用ThirdParty控件,我们需要构建这些笨拙的解决方案 . 基于@Anoop Muraleedharan的回答,我使用推理类型和ToolStripItem支持创建了此解决方案
你可以像这样使用它
我在MSDN forums找到了解决方案 . 下面的示例代码将删除
button1
中的所有Click
事件 .我找到了这个答案,它几乎符合我的需要 . 感谢SwDevMan81的课程 . 我修改了它以允许抑制和恢复单个方法,我想我会在这里发布它 .
好吧,这里有另一个解决方案来删除一个相关的事件(如果你已经有一个方法来处理控件的事件):
我刚发现How to suspend events when setting a property of a WinForms control . 它将从控件中删除所有事件:
我讨厌这里显示的任何完整的解决方案,我做了混合并现在测试,适用于任何事件处理程序:
简单!谢谢Stephen Punak .
我使用它是因为我使用通用的本地方法来删除委托,并且在设置不同的委托时,在不同的情况下调用本地方法 .
接受的答案不完整 . 它不适用于声明为{add;去掉;}
这是工作代码:
斯蒂芬说得对 . 这很容易:
这页帮助了我很多 . 我从这里得到的代码意味着从按钮中删除点击事件 . 我需要从某些面板中删除双击事件,然后单击某些按钮中的事件 . 所以我做了一个控件扩展,它将删除某个事件的所有事件处理程序 .
现在,使用这个扩展 . 如果您需要从按钮中删除点击事件,
如果您需要从面板中删除双击事件,
我不是C#的专家,所以如果有任何错误请原谅我,请让我知道 .
这不是OP的答案,但我想我会在这里发布,以防它可以帮助其他人 .