object ref not set ... resizing panel...

  • Thread starter Thread starter Nick Valeontis
  • Start date Start date
N

Nick Valeontis

I was writing a C# program this week. The program works okay in my pc (in
both debug and release builds) but realized that it would not work to other
pcs. It simply would close after displaying an "This program has encountered
an error etc etc etc.." popup.

I added some try, catch blocks and found that the error message was: "Object
reference not set to an instance bla bla". After spending some time to
locate the line that causes the problem, I again realized that the code was
generated by the designer! And .. that I have no idea at all of what is
really happening. The lines that cause the problem are:

this.Resize += new System.EventHandler(this.frmGraphics_Resize);
this.ResumeLayout(false);

frmGraphics function is:

private void frmGraphics_Resize(object sender, EventArgs e) {
UpdateControls();
}

UpdateControls is self explanatory. It checks if text in various controls of
the form should be updated.

Can anyone tell me why this code generates this error?

Note that if I change the lines

this.Resize += new System.EventHandler(this.frmGraphics_Resize);
this.ResumeLayout(false);

to

this.ResumeLayout(false);
this.Resize += new System.EventHandler(this.frmGraphics_Resize);

Then it will work okay.

So ... what is the catch??? :/ Does anyone have any idea?

-nick
 
Nick said:
I was writing a C# program this week. The program works okay in my pc (in
both debug and release builds) but realized that it would not work to other
pcs. It simply would close after displaying an "This program has encountered
an error etc etc etc.." popup.

I added some try, catch blocks and found that the error message was: "Object
reference not set to an instance bla bla". After spending some time to
locate the line that causes the problem, I again realized that the code was
generated by the designer! And .. that I have no idea at all of what is
really happening. The lines that cause the problem are:

this.Resize += new System.EventHandler(this.frmGraphics_Resize);
this.ResumeLayout(false);

frmGraphics function is:

private void frmGraphics_Resize(object sender, EventArgs e) {
UpdateControls();
}

UpdateControls is self explanatory. It checks if text in various controls of
the form should be updated.

Can anyone tell me why this code generates this error?

Note that if I change the lines

this.Resize += new System.EventHandler(this.frmGraphics_Resize);
this.ResumeLayout(false);

to

this.ResumeLayout(false);
this.Resize += new System.EventHandler(this.frmGraphics_Resize);

Then it will work okay.

So ... what is the catch??? :/ Does anyone have any idea?

Well, I would have to see the code for UpdateControls to be sure, but
let me hazard a guess.

Designer-generated code is run in a Form's constructor. At that point
in the process, the form doesn't have a window handle yet. That is, it
does not yet correspond to a real window on the screen. As such,
certain operations are illegal, and certain properties that don't
normally return null do in fact return null.

The way that the Designer wrote the original code:

this.Resize += new System.EventHandler(this.frmGraphics_Resize);
this.ResumeLayout(false);

I'm guessing that the ResumeLayour call causes the Form to arrange the
positions and sizes of controls on its surface and, perhaps, resize
itself accordingly. Since the Designer has already attached an event
handler for the Resize event, this may cause your frmGraphics_Resize
method to be called when ResumeLayout runs. Therefore, your method is
being called before the window handle is allocated, and maybe you're
trying, in effect, to use some property that doesn't have a value yet.

Again, I'm guessing, but I would suppose that the second ordering:

this.ResumeLayout(false);
this.Resize += new System.EventHandler(this.frmGraphics_Resize);

would cause all of the mucking about with control positioning and
window sizing to happen before the frmGraphics_Resize method subscribes
to the Resize event. So, the method will miss the first Resize (the
one that happens during construction when the window is sort of
half-built) and handle the second and subsequent Resizes (which
probably happen only after the window is loaded and so has a proper
window handle, etc).

All of this, of course is pure supposition on my part. The way to find
out if I'm right or just blowing smoke is to put a try...catch around
the UpdateControls call, like this:

try
{
UpdateControls();
}
catch (NullReferenceException nre)
{
MessageBox.Show(String.Format("UpdateControls caused exception:
{0}", nre));
}

This should show you a message box pinpointing the exact line where the
exception occurs. I think that you'll find that you're doing some
operation or using some property that isn't valid until the window is
fully constructed, during the Load method. If you find that that's the
case, you could always try this:

private void frmGraphics_Resize(object sender, EventArgs e) {
if (this.IsHandleCreated) {
UpdateControls();
}
}

to see if it sorts things out.
 
To be true need to see code in "UpdateControls". I am sure you might
have added some extra code to the genarated code.

"Object reference not set to an instance of Object" .... Try new of
the object before using the object.

also

Compile the code in "Any CPU" mode.

Thanks
-Srinivas.
 
Thanks!

You have really helped me isolate the problem.

I tend to add custom code after the call InitializeComponent() in the class
creator:

(Designer):
public frmGraphics(AStar newastar, string title) {
InitializeComponent();
astar = newastar;
...
}
private void frmGraphics_Resize(object sender, EventArgs e) {
UpdateControls();
}
}
private void UpdateControls() {
DrawPathsAndText();
UpdateErrorProvider();
}
private void DrawPathsAndText() {
using (Graphics g = pnlGraphics.CreateGraphics()) {
g.TranslateTransform(0, pnlGraphics.Height);
g.ScaleTransform((float)m_scale, -1 * (float)m_scale);

uxPrev.Enabled = uxFirst.Enabled = (m_index > 0);
uxNext.Enabled = uxLast.Enabled = (m_index < astar.Output.History.Count -
1);
...
...
}
}

So, what you describe makes sense here.

InitializeComponent calls UpdateControls, which calls DrawPathsAndText,
which tries to access properties of the astar instance. But astar has the
value of null, since the line "astar = newastar;" is not executed until
after InitializeComponent() is finished.

If I swap the lines in the frmGraphics creator:

public frmGraphics(AStar newastar, string title) {
astar = newastar;
InitializeComponent();
...
}
It works okay.

So, am I doing anything that is considered "bad practice" here?

Also, I would wonder. Why the error message does not appear when I run the
app in development pc?

Anyway, thanks again!


-Nick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top