views:

596

answers:

3

I tried to search for this, but I was not sure how to describe it. If it is a duplicate, please point me to the other question. Thanks.

I created a C# Windows Forms app using VS 2008. From the main form it opens a custom dialog form. When the user closes the dialog form, it does not completely disappear before the application starts into it's next task. The outline of various parts of the form remains until some additional tasks are completed.

This looks very unprofessional and it makes the application appear to be broken, even though everything works great. Is there any way to avoid and/or fix this problem?

FYI, the additional tasks are calculations requested after the form has been closed.

Here is the form closing code.

private void CloseForm_Click(object sender, EventArgs e)
{
    Properties.Settings.Default.EndDate = cmbBoxRptDate.SelectedValue.ToString();
    rptDate = cmbBoxRptDate.SelectedValue.ToString();
    Var1 = cmbBoxVar1.SelectedValue.ToString();
    Var2 = cmbBoxVar2.SelectedValue.ToString();
    this.Close();
}

Here is the code from the main form that opens the custom modal dialog and then disposes of it after it is closed. I think the dispose might be redundant since the form calls the close method on it's own.

RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();

Then a connection is established to SQL Server to do some report calculations.

+1  A: 

What you can do is to force the calling form to repaint itself after the dialog is closed, before carrying on with other stuff:

RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
this.Refresh(); // force repaint
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();

Note that there are two methods that will cause a form (or control) to repaint itself: Invalidate and Refresh. Refresh will force a full repaint immediately. Invalidate will not cause an immediate repaint, but rather invalidate the full control surface so that the full surface will be repainted the next time the control is updated (which may be delayed a bit if the thread is busy with other stuff, as in your case).

To force a repaint after calling Invalidate, you can call the Update method, which will force an immediate repaint of invalidated areas. So it may be, in your case, that you could simply call Update instead of Refresh, since I guess that the areas that were previously covered by the dialog should be invalidated. This might be more efficient that forcing a full repaint:

RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
this.Update(); // force repaint of invalidated areas
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();
Fredrik Mörk
Thanks for the help. This absolutely solved the problem.
JK
Glad it helped. That said; you should really look into Jon's advice, it's worth looking in to.
Fredrik Mörk
A: 

Looks like your main form is not getting refreshed. can you try calling this.Refresh() after showdialog?

chikak
+2  A: 

I suspect the last bit is the most important:

Then a connection is established to SQL Server to do some report calculations.

Is that still on the UI thread? If so, that's probably the problem - the repaint event for the main window is probably still waiting to happen, but you're busy with the database.

Fredrik's suggestion of calling Refresh is a good one, but you've still fundamentally got the problem of doing too much on the UI thread. If for whatever reason it takes a long time to establish a connection to SQL Server, your UI will be frozen during that time - you won't be able to move it, resize it etc.

Long-running operations - including just about anything to do with a database - should ideally be done on a different thread. This does make things trickier, without a doubt, but gives a much better UI in the end.

Jon Skeet
Thanks for the help, but this.refresh() was enough to do the trick.
JK
It may be while you've got a quick connection to the server and everything works fine - but you're still running the *risk* of an unresponsive application. I do appreciate that it makes the code a lot simpler though.
Jon Skeet
Thanks for the advice. I am definitely going to take your advice and work toward enhancing my application in this manner going forward. I gave a vote up for your help. Thanks Jon.
JK