How to remove and re-attatch EventHandler to controls in c#?

余生长醉 提交于 2019-12-05 10:02:51
Mohammad Dehghan

Here is a solution to your problem, according to this post of mine.

These helper methods let you manipulate any event for a specific control:

// Also searches up the inheritance hierarchy
private static FieldInfo GetStaticNonPublicFieldInfo(Type type, string name)
{
    FieldInfo fi;
    do
    {
        fi = type.GetField(name, BindingFlags.Static | BindingFlags.NonPublic);
        type = type.BaseType;
    } while (fi == null && type != null);
    return fi;
}

private static object GetControlEventKey(Control c, string eventName)
{
    Type type = c.GetType();
    FieldInfo eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName);
    if (eventKeyField == null)
    {
        if (eventName.EndsWith("Changed"))
            eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName.Remove(eventName.Length - 7)); // remove "Changed"
        else
            eventKeyField = GetStaticNonPublicFieldInfo(type, "EVENT_" + eventName.ToUpper());
        if (eventKeyField == null)
        {
            // Not all events in the WinForms controls use this pattern.
            // Other methods can be used to search for the event handlers if required.
            return null;
        }
    }
    return eventKeyField.GetValue(c);
}

private static EventHandlerList GetControlEventHandlerList(Control c)
{
    Type type = c.GetType();
    PropertyInfo pi = type.GetProperty("Events",
       BindingFlags.NonPublic | BindingFlags.Instance);
    return (EventHandlerList)pi.GetValue(c, null);
}

and then you can use them to temporarily detach an event handler:

private static void tb_LostFocus(object sender, EventArgs e)
{
    TextBox tb = (TextBox)sender;

    var eventList = GetControlEventHandlerList(tb);
    var eventKey = GetControlEventKey(tb, "TextChanged");

    // Remove the handlers
    var handlers = eventList[eventKey];
    eventList.RemoveHandler(eventKey, handlers);

    // ... perform your task

    // Reattach the handlers
    eventList.AddHandler(eventKey, handlers);
}

If you want to know what is really happening here, read on.

Windows Forms uses the EventHandlerList class to maintain control events. Every event is accessed using a simple key of type object. Keys are stored in private fields of the control. The only way to access this data is using reflection, but we should know the name of the event key field. By decompiling the the Control class and it's descendants, we can see that the keys use different names. I extracted three common naming pattern among the keys, and used them in the GetControlEventKey method.

This is the mechanism that WinForms controls use to hold the event handlers. There is no special thing about it. It is just a design choice.

DarckWarior

Remove

Mybutton.event -= methodname;

Reattach

Mybutton.event += methodname;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!