Most people working with WinForms have probably encountered that red X that is drawn over a control at some point and just doesn’t go away as long as the application is running. Originally, I had a look at the source of this some months ago and now, when I saw a relating question again, I thought I might document my findings here.
Note that I did that research with .NET 1 and I haven’t checked for .NET 2 yet, so in the latter case YMMV.
So where does the red X come from? Simple: The System.Windows.Forms.Control has an internal state flag for this that gets set when an exception is thrown in the control’s drawing code. So if you’ve never seen the red X but you want to, just throw a panel on a form and create a Paint event handler like this:
Now, the really interesting thing about the red X is that you can’t easily get rid of it once it’s popped up. The only “official” way is to restart the application. Lucky though that .NET has powerful reflection… that makes it possible to use the following method to reset the state:
So you can get that panel in the example above to have another go at drawing itself by going
Of course, if the same exception is still thrown from the paint handler, there won’t be much to see as the state is immediately set back to show the X again.
Generally, of course, you should have a very close look at the reason why there’s an exception thrown in the paint handling code at all. But there are situations where you might want to control the Control’s behaviour in detail and in these cases it’s nice to be able to handle that internal state yourself.
Two additional notes:
- You do need certain permissions to get that reflection code to run. If you want to configure your application for exact permission sets, you should use
[ReflectionPermission(SecurityAction.Demand, MemberAccess=true)]
in front of the ResetExceptionState method.- As I got a request for this at the time, I have a translation of the method in VB.NET, too. I don’t usually use VB, so there may be more elegant ways to do this, but here goes:
14 Comments »
WinForm Controls And The Red X
最新推荐文章于 2022-09-22 11:26:17 发布
I am facing the same problem when trying to open a form that contains a datagrid from
a .NET Visio Add-In.The datagrid appears with a Red X inside.
If i use the same form but from a windows application the grid loads correctly.
Any ideas,suggestions will be most welcome…
Many Thanks
Commen
Well, I think there may be not much you can do in this situation, because if the control in question is a third-party one, you might not be able to catch the exception that’s responsible for the red X to show up.
I’m also not getting the distinction you make: “a form that contains a datagrid” and “using the same form from a Windows application”? What’s the difference? How were you “using” the form in the first case, where the X shows up?
Comment by Oliver Sturm — 13/6/2005 @ 3:11 pm - 10 months, 2 weeks ago
The control is not a third party but the usual datagrid.
What i am doing is that i am creating a windows form and drag a datagrid into it.
If i add this form into a windows application and execute the app the grid opens fine (with no data).
When i am trying to open the form from a .NET Visio or excel Add-In i get the Red X.
Below is the source code from the visio add-in.
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
applicationObject = application;
addInInstance = addInInst;
Form1 frm=new Form1();
frm.ShowDialog();
}
In form1 i have simply added the default datagrid with no additional code
Thanks in advance,
Yiannis
Comment by Yiannis — 13/6/2005 @ 3:39 pm - 10 months, 2 weeks ago
Okay, now I understand what you’re saying I thought you were doing things the other way round, that’s why I was referring to a third-party control.
I’ve tried to do the same thing you’re doing, but it seems to work fine for me. I’m sorry, but I have no idea which specific circumstances might cause an exception to show up in your case.
Comment by Oliver Sturm — 14/6/2005 @ 6:20 pm - 10 months, 2 weeks ago
Hi,
thanks for your insight to the “Red X” problem.
I have situations where I get the “Red X” very often, only minutes after the application starts.
I’m using 3rd-party products etc. and most of the time the Red X happens completely random and out of my code.
No exception handler will catch the exceptions, just a Red X appears and so far only a reboot is a solution - which is very, very bad.
So, do you know of a way to *avoid* the Red X? There should be an exception, ok, but the Red X destroys the UI and thats a bad thing.
Is it possible to configure .NET to *not* draw a Red X?
Any hints greatly appreciated!
Walter
Comment by Walter — 29/6/2005 @ 6:56 pm - 10 months ago
Hi Walter - no, there’s no way to simply suppress the Red X completely. It’s .NET’s way of showing you that an error has occurred in a place where it influences the on-screen representation, and that this error wasn’t caught. The only solution to this is to find the error and fix it, or to catch the resulting exception.
The question really is simple: does it (the X) appear on one of your own controls (in which case you have a bug in your drawing code) or does it appear on one of the third-party controls (in which case they have a bug in their drawing code)? You should try tracking that down, maybe also try isolating the issues by testing the controls that are used in your application in smaller test scenarios.
If you are able to scale your application down to a small test and you still see the problem, and you have no idea what it might be about… if you want, I’ll have a look at it and see if I can figure anything out. But don’t send me largish stuff with lots of external references, please!
Comment by Oliver Sturm — 29/6/2005 @ 7:08 pm - 10 months ago
Thanks for your answer. The problems are:
+ the Red X appears randomly, there is no clear workflow that produces it
+ it appears in 3rd party controls and/or on .NET controls
+ the 3rd party says, “give me a sample”… but, no way, see 1st remark
I’m thinking of fetching the exceptions and then try to “correct” the
problem with your code (”SetState”).
Is there a way to check the state of a control, to see if there is a Red X
drawn on it (”GetState”)?
So I could check my controls and force a repaint on the broken ones.
Thanks for your help,
Walter
Comment by Walter — 29/6/2005 @ 9:24 pm - 10 months ago
Walter - yes, there is a method
bool GetState(int flag)
on the System.Windows.Forms.Control as well, so it’s possible to query the information in the same way, using Reflection. If you’re interested in that kind of thing, you should really get hold of Lutz Roeder’s Reflector here and have a look at the implementation of these details.The other thing, which maybe I shouldn’t say, is this: if you were working for me, I’d tell you to go find that problem! As you say, it happens on your own controls as well, but even if it wasn’t, the only real chance to get rid of these issues is to find an isolated test case that can reproduce them reliably. Sorry if this sounds harsh, but it’s that simple: if you haven’t found that test case yet, you haven’t looked hard enough. Just my opinion, of course.
Comment by Oliver Sturm — 30/6/2005 @ 8:37 am - 10 months ago
Oliver is correct, many times there is a solution to this problem by modifying your own code.
It is important to track these down, because they can rear their head when the bug is reached by another route, not handled by MS code.
The trick to tracking these down is to subclass the failing control, override the OnPaint method,
and catch exception there — print out stack trace.
This is why that works — the OnPaint method is called by the .NET framework with a special method named something like PaintWithErrorHandling, which then calls OnPaint.
If you subclass, you can get stack traces of the issue, rather than the framework swallowing the whole thing.
Sample call stack
sample OnPaint
Comment by John Covalesky — 11/7/2005 @ 6:33 pm - 9 months, 3 weeks ago
Thanks for all your suggestions.
In the meantime I have implemented an application exception handler
that fetches all unhandled exceptions, including the ones that
lead to a red cross.
When this happens I try to automatically repaint all forms/controls. This
approach now works fine.
I know this is just a workaround, but when the “Red X” occurs there is none
of my code involved… The call stack often just shows System.* - classes.
Even worse, I only have to move windows across the screen and suddenly a
“Red X” appears. In other situations its a 3rd party control that does
repainting etc. Nothing I can debug or fix here.
The only reason I can guess about is an old 3rd party tool we have to
incorporate in our .NET Forms using the tricky and unsupported way of
using SetParent(). This is a bad thing, I know, but it’s a *must*. And
replacing that old tool with new .NET Forms will take a long time
- but it will be done.
Thanks,
Walter
Comment by Walter — 23/7/2005 @ 12:12 pm - 9 months, 1 week ago
Hi Walter, nice to hear you found a solution. I think that the tool you are mentioning may be a good guess for the source of your problems. Thanks for keeping us updated!
Comment by Oliver Sturm — 24/7/2005 @ 9:39 am - 9 months, 1 week ago
Hi,
I have this problem when I reject changes to dataset of a datagrid.
I set the .Visible property of the datagrid to false and after
changing data I set it to true back.
this workaround fixed my datagrid RED X / RED Cross problem.
best RegardsZ
Mehdy Mohajery
–
Comment by Mehdy Mohajery — 6/12/2005 @ 11:34 am - 4 months, 3 weeks ago
Hi,
I have being seeing a “red x” appearing in place of a datagrid, but this is very rare. I do have a custom column style, and am leaning towards its’ overriden OnPaint() method as being the culprit. The custom paint method is attempting to color the rows in the columnn based on the cell contents.
Wondering if you could point out any errors in the following method? Thanks so much!
Comment by Andrew — 6/2/2006 @ 3:27 pm - 2 months, 3 weeks ago
Well, obviously your code could easily throw an exception as soon as the type of o is one that can’t be cast to a string. I would rewrite that section as
Looks nicer and can’t go wrong. Now, as you’re still catching everything in the outer try/catch, I still have no idea why that routine would throw an exception. I don’t remember things as closely as I did when I wrote this post, maybe there are other interesting code paths due to the fact that you’re using an overridden method instead of an event handler? I suggest you get Reflector and find out