Search code examples
c#winformseventsevent-handlingformclosing

How to remove Closing event?


I have found a nice example of how to remove all Click events from a form:

private void RemoveClickEvent(Form c)
{
    var f1 = typeof(Control).GetField("EventClick", BindingFlags.Static | BindingFlags.NonPublic);
    var obj = f1.GetValue(c);
    var pi = c.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
    var list = (EventHandlerList)pi.GetValue(c, null);
    list.RemoveHandler(obj, list[obj]);
}

and it works well. However, what I need is to remove Closing event but I have no clue as of what to write instead of EventClick to make it work. I tried to write EventClosing, Closing, but that didn't work. Thus my question is: what should be changed to make it work? Even better - I would like to find a list of all possible inputs there since I might need to remove other events like Closed, FormClosing, FormClosed, etc.

P.S. a simple -= is not possible since there can be many events attached many of them not accessible to me at all thus I wouldn't be able to remove them anyway.


Solution

  • As mentioned in the comments I have come up with a list of these event names with this:

    typeof(Form).GetFields(BindingFlags.NonPublic | BindingFlags.Static).AsEnumerable().ToList();
    

    Now I have a method which looks like this:

    public static class Utils
    {
        public static void DisableEvents<T>(this T ctrl, string officialName, string simplifiedName) where T : Control
        {
            var propertyInfo = ctrl.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
            var eventHandlerList = propertyInfo.GetValue(ctrl, new object[] { }) as EventHandlerList;
            var fieldInfo = typeof(T).GetField(officialName, BindingFlags.NonPublic | BindingFlags.Static);
            var eventKey = fieldInfo.GetValue(ctrl);
            var eventHandler = eventHandlerList[eventKey];
            var invocationList = eventHandler.GetInvocationList();
    
            foreach (var item in invocationList)
            {
                ctrl.GetType().GetEvent(simplifiedName).RemoveEventHandler(ctrl, item);
            }
        }
    }
    

    And the usage looks like this:

    myForm.DisableEvents<Form>("EVENT_CLOSING", "Closing");
    

    Unfortunately I am yet to have come up with a way to pass a single parameter to my method.