I have a WinForms form that won't close. In OnFormClosing, e.Cancel is set to true. I am guessing that some object in my application has bound to the Closing or FormClosing event, and is blocking the close. To find out, I'd like to determine what delegates are bound to one of these events.
Is there a way to determine the list of handlers bound to an event? Ideally I would do this via the Visual Studio debugger, but can write code in the application to find the handlers if necessary. Understanding that an event is like a hidden private field, I've navigated through the Debugger to the "Non-Public Fields" for the "Windows.Forms.Form" ancestor of my form, but to no avail.
However, there are two other ways of registering event handlers that you might see: event handler properties and inline event handlers.
Right-click on the search icon button and choose “inspect” to open the Chrome developer tools. Once the dev tools are open, switch to the “Event Listeners” tab and you will see all the event listeners bound to the element. You can expand any event listener by clicking the right-pointing arrowhead.
Here are some common examples of an event handler: A notification pops up on a webpage when a new tab is opened. A form is submitted when the submit button is clicked. The background color changes on a mouse click.
An event handler, in C#, is a method that contains the code that gets executed in response to a specific event that occurs in an application. Event handlers are used in graphical user interface (GUI) applications to handle events such as button clicks and menu selections, raised by controls in the user interface.
In short, you're not meant to do this - but for debugging purposes...
An event is often backed by a private field - but not with controls; they use the EventHandlerList
approach. You would have to access the form's protected Events
member, looking for the object mapped to the (private) EVENT_FORMCLOSING object.
Once you have the FormClosingEventHandler
, GetInvocationList
should do the job.
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); } } }
The problem might be that the form doesn't validate.
The FormClosing
event is raised by the private WmClose
method in Form
, which initializes e.Cancel
to !Validate(true)
. I haven't investigated, but in certain circumstances, Validate
will always return false
, causing the close to be canceled regardless of any event handlers.
To investigate this, enable .Net source debugging, put a breakpoint in your FormClosing
handler, go to the source for Form.WmClose
(up the call stack), put a breakpoint at the beginning of WmClose
, and close the form again. Then, step through it in the debugger and see why Validate
is returning false
. (Or which event handler is setting e.Cancel
to true)
To solve the problem, set e.Cancel
to false
in your own handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With