eventos - invocar evento c#
Determine la lista de controladores de eventos vinculados al evento (2)
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é delegados 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.
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 pila 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.
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);
}
}
}