Caster Troy
Caster Troy

Reputation: 2866

Controls are white when I display new form

Because this is turning out to be quite a large project and I often need to access objects in other forms from a class I firstly create a static variable in my program.cs class of type 'MainForm'which is a Windows Form.

From my DataManger.cs Class, I instantiate the object 'Program.MainFormObj = new MainForm()' and then call the Show method in order to display my Form. It looked like the the Paint event for the form doesn't get to finish but it does kick off as some controls are drawn. Presumably because the main thread (this is all running on one the main thread) is 'occupied' by the next statement. I figured, regardless of known problems I'd use Application.DoEvents() to temporarily counter this issue. As I imagined, it worked, but only to a certain extent. If I put a blocking method like MessageBox.Show(), I can view my completely flawless form in the background but as soon as I press 'OK' and the code proceeds the entire application exits.

I'm really stuck. Despite some extensive searching both here and using Google I can't find an apporpiate answer. I did this this thread: Form.Show() is not showing it's child controls but the given solution isn't appropriate for my solution. Any help is appreciated very much, thanks.

Upvotes: 2

Views: 2911

Answers (1)

Eric J.
Eric J.

Reputation: 150228

If this is a large project, invest time now to refactor it.

  • Consider an MVC pattern. You can do what with WinForms, not just newer UI technologies.
  • If you do not opt for WinForms, at least separate UI and data (Data Binding is your friend).
  • Build reusable components when different forms share common functionality.

Fighting the way WinForms works will be much more expensive in the mid-term than investing time now to do things right.

If you have any choice about the technology, consider WPF instead. There is a learning curve with WPF, but it may well be worth investing in that learning now.

UPDATE

Based on your code sample, I see that you are probably creating some of your forms on a thread other than the main UI thread. While that is allowed, it creates for very confusing code because forms can only be updated from the thread they were created on.

The simplest hack to get this working is probably to update HandleIncomingData to also invoke the Show() calls on the main UI thread.

There is supposed to be a way to cleanly do that from a static method, outlined here:

https://stackoverflow.com/a/505361/141172

However, when I tried that, I found that SynchronizationContext was always null. I'm sure I'm just missing a step.

I was able to get things working by misusing the LoginForm (assuming, perhaps incorrectly, that the form is always available. If not, perhaps create a special form just for thread marshaling).

The hack looks like this:

Program.MainForm = new MainForm();
try
{

    MessageBox.Show("Login Success.", "Login", MessageBoxButtons.OK, MessageBoxIcon.Information);

            // Abusing LoginForm's Invoke method.  Code assumes LoginForm is always available.
    Program.LoginForm.Invoke((MethodInvoker)delegate
    {
        Program.MainForm.Show();
    });


}
catch (Exception Ex)
{
    MessageBox.Show(Ex.ToString()); //Debuging purposes
}

By the way, there's an excellent extension method that makes it a breeze to invoke UI code from a non-UI thread:

https://stackoverflow.com/a/3588137/141172

Upvotes: 2

Related Questions