从Eventhandler中删除所有方法

时间:2013-06-04 06:38:19

标签: c# events event-handling

在你开始问我为什么要这样做之前,请记住我对Windows.Forms没有太多经验,此时我只是在试验。

假设我用5个按钮组成。就像每个按钮一样,按下它后它应该做一些事情。我发现我可以为这样的事件添加多个方法:

button1.Click += DoThis;
button1.Click += ButAlsoThis;

我为每个按钮都这样做了。然后我尝试创建一个方法来删除给定按钮的所有方法。像这样:

public void RemoveHandlers(Button btn)
{
    //Code to remove handlers
}

这就是我被困的地方......

我希望C#会接受这样的事情:

btn.Click = null

但很显然,事件只接受'+ ='和' - ='。

所以现在我有了这个精心设计的系统,我有一些按钮和一个EventHandlers列表,与一个dictionairy链接。然后我单独删除每个Eventhandler。它有效...但我认为应该有一个更简单的方法。

故事很长:

是否有一种简单的方法可以在事先不知道所涉及的处理程序的情况下从事件中删除所有处理程序?

编辑,我找到了答案,感谢Carlos Landeras:

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]);
}

但我只是不想复制+粘贴,我想知道这里发生了什么。

2 个答案:

答案 0 :(得分:2)

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]);
}

检查一下,正是您所寻找的:

How to remove all event handlers from a control

答案 1 :(得分:0)

class Program
{
    private event EventHandler demoEvent;

    static void Main(string[] args)
    {
        Program p = new Program();
        p.demoEvent += new EventHandler(Program_DemoEvent);
        var list = p.demoEvent.GetInvocationList();
        var demoEventType = typeof(Program).GetEvent("demoEvent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        MulticastDelegate myValue = typeof(Program).GetField("demoEvent", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetValue(p) as MulticastDelegate;
        var invocationList = myValue.GetInvocationList();
        foreach (var handler in invocationList)
            demoEventType.RemoveEventHandler(p, handler);
    }

    static void Program_DemoEvent(object sender, EventArgs e)
    {

    }
}