Form controls not rendering

Viewed 75

I'm having troubles rendering my custom non blocking 'MessageBox' like form. So I have made my Alert form:

public partial class Alert : Form
{
    public Alert(string title, string text)
    {
        InitializeComponent();
        this.Text = title;
        labelText.Text = text;
    }

    private void buttonOk_Click(object sender, System.EventArgs e)
    {
        Close();
    }
}

and looks like this in designer:

enter image description here

But when I try to open this Alert form within my main form like this:

var alert = new Alert("Test", "Hello, this is test.");
alert.Show();

Then my Alert form renders like this:

enter image description here

Where is my button and label?

//EDIT

alert.ShowDialog();

renders the form as intended

The method I'm using this form in:

    private void buttonTestConnection_Click(object sender, EventArgs e)
    {
        var f = new Alert("Test", "Hello, this is test");
        f.Show();
        Thread.Sleep(2000);
        var result = TestSqlConnection(); // This may that a while 
        if (result)
        {
            f.Close();
            MessageBox.Show("Test", "Test successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        else
        {
            f.Close();
            MessageBox.Show("Test", "Connection failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
2 Answers

The UI thread renders your UI. You are blocking the UI thread by calling Thread.Sleep. Thread.Sleep has it's place in programming, but not in UI programming.

My suggestion would be to move to asynchronous programming. For example:

private async void buttonTestConnection_Click(object sender, EventArgs e)
{
    var f = new Alert("Test", "Hello, this is test");
    f.Show();
    await Task.Delay(2000);
    var result = await Task.Run(() => TestSqlConnection());
    if (result)
    {
        f.Close();
        MessageBox.Show("Test", "Test successful",
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    else
    {
        f.Close();
        MessageBox.Show("Test", "Connection failed",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Notice the async keyword added to your method signature and calls to await.

I won't go in to how this works as there are many, many tutorials online. Here is a great place to start. The guy is a resident genius around here when it comes to this pattern.

Typically SQL connections can be converted to asynchronous, so that Task.Run should be temporary until you figure out the pattern.

Another quick example:

private async void buttonTestConnection_Click(object sender, EventArgs e)
{
    buttonTestConnection.Enabled = false;

    using (var f = new Alert("Test", "Hello, this is test"))
    {
        f.Show();
        bool result = await Task.Run(() => {
            Thread.Sleep(2000);
            return TestSqlConnection();
        });
        MessageBox.Show("Test", "Test " + (result ? "successful" : "failed"), 
            MessageBoxButtons.OK, 
            (result ? MessageBoxIcon.Information : MessageBoxIcon.Error));
    }

    buttonTestConnection.Enabled = true;
}
Related