You are making a WinForms app. All is going well, until one day your custom control disappears. In its place you just see a big red cross:
Let us back up to remind ourselves how exceptions work:
- If your code does something wrong (such as dereferencing a null object or passing invalid parameters to an API) an exception is thrown
- If your code catches the exception, it can handle the error and continue along its merry way
- If the exception is not caught, the program terminates
- If the debugger is attached when an unhandled exception occurs, it pops up a window showing the exception message and callstack, so you can see exactly what went wrong
WinForms extends this system in one important way:
- It wraps calls to your Control.OnPaint method in a try/catch block
- If OnPaint throws an exception, this is now caught by WinForms rather than left unhandled
- WinForms keeps track of whether OnPaint has ever thrown an exception
- If so, it skips any later calls to OnPaint, and instead just draws a red cross
I don't know why WinForms decided to do this, but it's kinda annoying because if anything goes wrong in your OnPaint code, the debugger never gets to see the exception so has no chance to show you the exception message!
To debug such problems, open up the Debug \ Exceptions menu in Visual Studio and check the Thrown box next to Common Language Runtime Exceptions. Now the debugger will break whenever any exception is thrown, regardless of whether or not it is caught further up the stack, so you can see the original message and callstack in spite of WinForms trying to catch this error.