Determine la lista de controladores de eventos vinculados al evento

Tengo un formulario de WinForms que no se cierra. En OnFormClosing, e.Cancel está establecido en verdadero. Supongo que algún objeto en mi aplicación se ha vinculado al evento Closing o FormClosing, y está bloqueando el cierre. Para averiguarlo, me gustaría determinar qué delegates están obligados a uno de estos eventos.

¿Hay alguna forma de determinar la lista de controladores vinculados a un evento? Idealmente, haría esto a través del depurador de Visual Studio, pero puedo escribir código en la aplicación para encontrar los manejadores si es necesario. Entendiendo que un evento es como un campo privado oculto, he navegado a través del Depurador hasta los “Campos no públicos” para el ancestro “Windows.Forms.Form” de mi formulario, pero fue en vano.

En resumen, no se supone que hagas esto, sino para depurar …

Un evento a menudo está respaldado por un campo privado, pero no con controles; usan el enfoque EventHandlerList . Tendría que acceder al miembro de Events protegidos del formulario, buscando el objeto asignado al objeto (privado) EVENT_FORMCLOSING.

Una vez que tenga el FormClosingEventHandler , GetInvocationList debería hacer el trabajo.


 using System; using System.ComponentModel; using System.Reflection; using System.Windows.Forms; class MyForm : Form { public MyForm() { // assume we don't know this... Name = "My Form"; FormClosing += Foo; FormClosing += Bar; } void Foo(object sender, FormClosingEventArgs e) { } void Bar(object sender, FormClosingEventArgs e) { } static void Main() { Form form = new MyForm(); EventHandlerList events = (EventHandlerList)typeof(Component) .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(form, null); object key = typeof(Form) .GetField("EVENT_FORMCLOSING", BindingFlags.NonPublic | BindingFlags.Static) .GetValue(null); Delegate handlers = events[key]; foreach (Delegate handler in handlers.GetInvocationList()) { MethodInfo method = handler.Method; string name = handler.Target == null ? "" : handler.Target.ToString(); if (handler.Target is Control) name = ((Control)handler.Target).Name; Console.WriteLine(name + "; " + method.DeclaringType.Name + "." + method.Name); } } } 

El problema podría ser que el formulario no valide.

El evento FormClosing es generado por el método privado WmClose en Form , que inicializa e.Cancel para !Validate(true) . No he investigado, pero en determinadas circunstancias, Validate siempre devuelve false , lo que hace que el cierre se cancele independientemente de cualquier controlador de eventos.

Para investigar esto, habilite la depuración de origen de .Net , ponga un punto de interrupción en su manejador de FormClosing , vaya a la fuente de Form.WmClose (suba la stack de llamadas), ponga un punto de interrupción al comienzo de WmClose y WmClose cerrar el formulario. Luego, páselo en el depurador y comprueba por qué Validate devuelve false . (O qué controlador de eventos está configurando e.Cancel en verdadero)

Para resolver el problema, configure e.Cancel a false en su propio controlador.