none
Setting Dock to Fill is not propagating properly in control hierarchy with split containers RRS feed

  • Question

  • I have a form with a number of nested split containers which hold a set of user controls that display various grids.  The top part of the form controls looks like this:

    The scGridAndRecord.Panel1 has a set of six user controls called ctlEntitiesList which are created and initialized at run time and inserted into the list of controls for Panel1.  When a user picks a node on the tree to the left, it fires this code to 'hide' the current user control and display a different one from the list.

                'scGridAndRecord.SuspendLayout()
                scGridAndRecord.Panel1Collapsed = False
                scGridAndRecord.Panel2Collapsed = True
                Dim listCtl As ctlBaseList = dynamicControlsList.Item(Category.CategoryName)
                If activeList Is Nothing OrElse Not activeList.Equals(listCtl) Then
                    If activeList IsNot Nothing Then
                        activeList.Visible = False
                        activeList.Dock = DockStyle.None
                    End If
                    activeList = listCtl
                    activeList.Visible = True
                    activeList.BringToFront()
                    activeList.Dock = DockStyle.Fill
                    'activeList.Refresh()
                End If
    

    The problem occurs at the Dock property.  When this is set, the first time it runs, the result looks like this:

    Clearly, the big black area is not supposed to be there, instead there should be a grid control that fills the space.  If I comment out the dock, I get the following with no black box, but no re-size to fill the space:

    There are no Exceptions generated, no error messages, but the dock property and the controls somehow stop re-sizing themselves.  The user control is basically a user control wrapped around a standard grid. The Grid has the Dock property set to Fill.  Oddly enough, clicking on a second node on the tree causes everything to work properly, it is only the first time through that this does not work.  I have tried adding Application.DoEvent, queing an asynch task to set the Dock Property 'later', nothing has any effect.  I also commented out suspend/resume layout and refreshing the control - nothing seems to have an effect that I have tried.  I also tried changing the order of setting the user control to visible, again with no effect.

    Can anyone suggest a work-around to this problem?

    Thanks, Neil


    Neil M. Johnson

    Thursday, May 11, 2017 9:20 PM

Answers

  • As always with these type of problems, it turned out to be a self-inflicted wound.  In the control which has the grid, I had added an 'optimization' which would allow outer controls to turn off grid layouts while data was being laid out and the routine was named (I bet you can see where this is going) 'SuspendLayout' with its matching partner being 'ResumeLayout'.  Unfortunately, the control itself also in the designer also calls SuspendLayout() and then ResumeLayout(False).  My code provided the first call but did not provide a resume layout with a parameter, so the ResumeLayout never got called and the embedded grid never got resumed. I renamed the two calls to BeginDataLoading and FinishDataLoading and the whole thing works as it should.

    To clarify - this is not a Microsoft problem - it is a nut loose behind the keyboard problem.

    Thanks to everyone for their suggestions,

    Neil


    Neil M. Johnson

    Tuesday, May 16, 2017 1:23 AM

All replies

  • Perhaps right before docking fill you manually set the size of the control to the client area (which docking should do) then set docking, Yes you should not have to do this and if it works is a work-around, if it works great until you figure out something else e.g. via an event that maybe the docking should be done in yet I don't know that currently.

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Thursday, May 11, 2017 10:28 PM
    Moderator
  • Yes, I feel your pain. Events within events. You never know what will happen and what size something will be. Impossible to step through the code to see what it is "really" doing.

    Sometimes you can just call your resize event at the proper moment. ie after whatever is changed changes. Since it works for you the second time, just force the second time the first time?

    ie   form1_resize(0, nothing)


    PS If the six controls are the same can you just fill the same control with six sets of data? etc. I would look to try and simplify what you have going although I dont understand what you have either.

               "Doctor it hurts when I do this"

                 Doctor: "Dont Do That!"

    PSS I am assuming you have code in the resize event that is resizing controls etc.

    You can also try

       Me.PerformLayout

       Me.PerformAutoScale

    Thursday, May 11, 2017 11:04 PM
  • Karen, good suggestion. However, I tried this and got the exactly same result, even with removing the Dock statement.  In debugging, setting the UserControl to the ClientSize of the Panel1 showed that the UserControl did change size correctly.

    It appears that either the inner control or the grid it contains is not getting the Resize message properly.  The grid in the control is itself a control that inherits from the DataGridView control and adds the ability to remember column sizes and positions.  I replaced this control with the original DataGridViewControl and got a slightly different behavior - the inner grid did not resize, but the black box was gone.  Somehow the UserControl seems to be the culprit here, but I am not sure how.

    Thanks, Neil


    Neil M. Johnson

    Thursday, May 11, 2017 11:09 PM
  • Hi

    Just my tuppence worth.

    I had an application which had a similar type of thing as you describe.

    It had many nested SplitContainers, each with one or more controls and a couple were 'dynamic' in as much as they were resized according to some user settings, or resizing according to font sizes used etc, and if I remember correctly, they were all docked fill in respective Panel.

    Although I did have a few mishaps in the early designs, I eventually managed to get them all in sync with requirements.

    I realize that this isn't an answer, sorry, more of a 'keep at it - it is possible'.

    I can't show any code as my application became useless when the PVR it was driving became a historic relic and had to be sent to the great TV in the sky.


    Regards Les, Livingston, Scotland

    Friday, May 12, 2017 12:56 AM
  • As always with these type of problems, it turned out to be a self-inflicted wound.  In the control which has the grid, I had added an 'optimization' which would allow outer controls to turn off grid layouts while data was being laid out and the routine was named (I bet you can see where this is going) 'SuspendLayout' with its matching partner being 'ResumeLayout'.  Unfortunately, the control itself also in the designer also calls SuspendLayout() and then ResumeLayout(False).  My code provided the first call but did not provide a resume layout with a parameter, so the ResumeLayout never got called and the embedded grid never got resumed. I renamed the two calls to BeginDataLoading and FinishDataLoading and the whole thing works as it should.

    To clarify - this is not a Microsoft problem - it is a nut loose behind the keyboard problem.

    Thanks to everyone for their suggestions,

    Neil


    Neil M. Johnson

    Tuesday, May 16, 2017 1:23 AM