Prevent winforms control from becoming visible when dynamically adding to Controls collection

StackOverflow https://stackoverflow.com/questions/20263547

  •  06-08-2022
  •  | 
  •  

Pergunta

I have created a Form with a loading Panel on it. The idea being that I want to show this loading panel until my dynamically created control is ready to display.

The loading Panel is visible initially, and then during the OnShown event I am creating my control and adding it to the page. The reason I am using OnShown is that the Form is being used in an Mdi scenario so I need it to be fully displayed before I start loading the control (if I try this in the Load event then the Mdi Tab doesn't display until my control is loaded).

The problem is that there is noticable flicker which I believe is due to the fact that when I add my control to the Controls collection:

a) the Visible property is immediately set to true. b) my control seems to appear in front of the loading Panel even though the z-index appears to be correct.

Here is the nub of the issue

    protected override void OnShown(EventArgs e)
    {
        Debug.WriteLine(loadingPanel.Visible); //true
        Debug.WriteLine(Controls.GetChildIndex(loadingPanel)); //0

        Debug.WriteLine(myControl.Visible); //false

        myControl.Visible = false;
        Controls.Add(myControl);
        //**

        Debug.WriteLine(myControl.Visible); //true

        Debug.WriteLine(Controls.GetChildIndex(loadingPanel)); //0
        Debug.WriteLine(Controls.GetChildIndex(myControl)); //1

        Debug.WriteLine(loadingPanel.Visible); //true

        base.OnShown(e);
    } 

I was hoping that I could add my control to the collection and it would remain Visible = false so that I could set Visible = true when my control's Load event had completed. Instead, my control comes into view and I get flickering. Interestingly, if I don't set loadingPanel.Visible = false at any point then once my control has finished loading, the loadingPanel re-appears and hides my control.

Any ideas?

Foi útil?

Solução 3

Somewhat strangely, this is how I managed to solve my issue:

protected override void OnShown(EventArgs e)
{
    //trigger the OnLoad event of myControl - this does NOT cause it to appear
    //over the loading Panel
    myControl.Visible = true;
    myControl.Visible = false;  //set it back to hidden

    //now add the control to the Controls collection - this now does NOT trigger the
    //change to Visible, therefore leaving it hidden
    Controls.Add(myControl);

    //finally, set it to Visible to actually show it
    myControl.Visible = true;

    base.OnShown(e);
} 

I can only assume that when adding a control to the Control collection then if the handle is not created it will auto set it to Visible. By making it visible before adding it to the collection, the relevant handles are created by do not affect the parent control. Then when it is added to the collection later on, it still does not interfere with the parent control.

Outras dicas

I take it your mycontrol is a standard winforms control? Why not create a custom control with the desired mycontrol in it, and in that custom control, default the "child" control's visible property to false?

Have not tested this, but thats what I would do next...?

You don't need to change the Visible that way, even when you set it to false successfully, when you show them back, there is still some flicker if the number of controls is large. You should override the OnLoad method, and use SuspendLayout and ResumeLayout like this:

//Start adding controls
SuspendLayout();
//....

//in the OnLoad
protected override void OnLoad(EventArgs e){
  ResumeLayout(true);
}

I doubt that using ResumeLayout(true) right after finishing adding controls may be OK, you should also try that.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top