ContainerControl Placement

I’ve just been looking at some containercontrol options and found 2 ways to achieve the same thing, and Im wondering what the best way is.

The main screen of the app has a simple navigator column with 5 clickable options on the left side, then the remaining area of the screen has a pagepanel to hold the containercontrols, of which there are 5 corresponding ones.

From playing around with it, I can do one of two things:

  1. Add a total of 5 pages to the pagepanel, then load each of the container controls onto the respective page, then navigate by changing the pagepanel.value.

  2. Have a single page on the pagepanel, then dim a new instance of the respective containercontrol when the option is clicked, and embed it within the pagepanel.

Is there a specific way I should be doing this, or are both options acceptable ?

Both are acceptable, but if your 5 pages are static, it seems like it would be easier to just set them all up in the designer rather than adding them at run-time.

Thanks for the quick answer Paul, but static in what respect ?

Four of them will have a custom listbox, and a few editfields relating to database records loaded in the listboxes, and the last will simply have a small number of editfields but no listbox.

The only thing that comes to mind from the above options is that if I load them all in the designer then run the app, if a user switches between them half way through an edit, then switches back the half completed edit remains as it was.

The second option gives a new clear instance with previous (uncompleted) edits discarded.

I would be really annoyed if my edits just disappeared …

There is that yup.

The perfectionist in me says that you shouldnt be switching between different screens in the middle of an edit without first committing or reverting changes. Im split on which option to use.

I mean static in that there are always 5 pages and they always have the same controls on them, which is what it sounds like you have.

Thanks Paul and Markus.

I’ll give this one some more thought.

Maybe add a “containerIsDirty” property to your cc subclass, and check for that on view changes…

So I had a think about this and decided to use a single page in the PagePanel control and then create a new instance of each ContainerControl as and when a navigation option is clicked. Then I use embedwithinpanel(pagepanel, 0) to display the container control. The problem I now have is that i cant close or destroy the existing one when I want to place a new one.

/ Add default first instance
Dim MyContainer1 As New ContainerControl1
MyContainer1.EmbedWithinPanel(PagePanel, 0)

/ A new navigation option is clicked so do it again with the corresponding container
Dim MyContainer2 As New ContainerControl2
MyContainer2.EmbedWithinPanel(PagePanel, 0)

The problem when adding the second one is that it overlays on top of the first and the screen looks a mess. The obvious thing here is to get rid of the original before loading the second, I cant seem to get that to work though. I’ve tried the following :

MyContainer1.Close

Window1.MyContainer1.Close ’ (Didnt really expect this one to work but tried anyway)

Window1.PagePanel.MyContainer1.Close

Window1.PagePanel(0).MyContainer1.Close

I’m sure it is something simple I need; how do I get rid of that original instance ?

The EmbedWith has optional parameters for X, Y, width, and height so you can control placement. Nothing stopping you from changing those after the embed afterwards either.

To remove it, set the Visible property = false, first. Then call close and set the variable to nil. That should cover all your bases.

I have the parameters all working Bob, but any of the above attempts to close it result in ‘This item does not exist’.

After I posted I realised it would be much simpler to do away with the PagePanel and just embed the container controls directly within the window always at the same location, but it still begs the question, how is it achieved when embedded within a pagepanel ?

I’m unsure if this applies to pagepanels, but I embed containercontrols inside a canvas on the main window. When the container needs to be changed, I just set the original container=nil, and then embed the new container within the canvas.

You must save a reference to the container in a window property or better. Dim MyContainer1 As New ContainerControl1 creates a local, throw-away variable. You lose track of it as soon as the method returns. Later, there’s no way to refer to the container, because you lost the reference.

My containercontrols are relatively straight forward and I can place them directly in the parent window, so no actual pagepanel or canvas needed, although there is an option of putting said container on a PagePanel and then simply deleting the page, which would destroy the panel. Not elegant by any measure.

Is there another option for this then ? Maybe relocate the calling code somewhere in the parent window itself instead of in a global method where it currently is ?

It doesn’t matter where the code is, although it should be in the window for better encapsulation. The real issue is where the variable is. Right now, you’ve got it local, which is causing the problem. Add a property to the window

MyContainer as ContainerControl

Keep it generic, so you can assign any of your controls to it. Change your code to

/ Add default first instance
MyContainer = New ContainerControl1
MyContainer.EmbedWithinPanel(PagePanel, 0)
/ A new navigation option is clicked so do it again with the corresponding container
if MyContainer <> Nil then MyContainer.Close
MyContainer = New ContainerControl2
MyContainer.EmbedWithinPanel(PagePanel, 0)