I'm creating a WinForms app with picture boxes which are disabled and not visible by default. When I click on a radio button in my form, I want the picture boxes to appear and immediately after that I want something to be drawn over them:
// the radio button CheckedChanged event handler:
table1PictureBox.Enabled = true;
table1PictureBox.Visible = true;
DrawCorrectAnswers(); // draw something over the picture box
The problem is that the drawing finishes before the picture is made visible, so the drawing is ultimately covered by the picture.
While solving the problem I read here that after Visibility is set to true, the actual image load is queued in the message queue of the form. The answer even suggests that a possible solution is to set a timer and then asynchronously wait for its tick and then do the drawing, so that the pictures have time to load. I don't like the solution with setting a timer, instead I would like to wait for the pictures themselves to be loaded.
Is there a way to do this? How exactly does setting Visible to true work in this case?
I also tried to come up with an alternative solution which looked like this:
// the radio button CheckedChanged event handler:
table1PictureBox.Enabled = true;
table1PictureBox.Visible = true;
this.BeginInvoke(new Action(() => { DrawCorrectAnswers(); })); // 'this' is the form
My idea was that this would enqueue the message for drawing after the message for loading, so even the operations would be performed in the required order. This, however, didn't work either.
In this case, might there be a special behavior of BeginInvoke if I'm in the thread of the form? I even tried normal Invoke and to my surprise, it didn't cause a deadlock. Why is that?
[EDIT] Here is a minimal example that illustrates the problem:
public Form1()
{
InitializeComponent();
pictureBox1.Visible = false;
pictureBox1.Enabled = false;
}
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Enabled = true;
pictureBox1.Visible = true;
Graphics graphics = pictureBox1.CreateGraphics();
graphics.DrawLine(Pens.Black, 0, 0, 50, 50);
}