Reference to a Form stored in a Public Property


I have a Main form called Designer.  The Designer has a StatusBar.  The Designer also has two panels (Panel1 and Panel2).  Each Panel has a Form to show.  I have decided that there is no need to have multiple StatusBars, only the one on the Designer.

On the Form opened in Panel1 I store the StatusBar values in an ArrayList.  I want to pass this ArrayList to the Parent Designer Form Public Sub that updates the StatusBar.

So to update the StatusBar on the Designer I need a reference to the Designer form.  Could I use a Public Property defined as Object or Variant?  Would/Could I assign the value of the Public Property just after I create it?


Dim frm as new FormA
frm.p_FormInstance = frm

Then I could do something like:
call p_FormInstance.subUpdateStatusBar(aList)

aList is the list of two settings for the StatusBar to update.
Peter AllenAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David L. HansenCEOCommented:
Take a look at "my.forms...." you can usually reference your forms directly using that.
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Is "Designer" the MAIN form that the application STARTS with?  Is it also the value set as the "Startup Object" in Project --> Properties?

If yes to both, then you can simply reference the Designer "BY NAME" as the default instance is what is displayed.

So, from within FormA, you can simply do:

Miguel OzSoftware EngineerCommented:
You need to cast p_FormInstance to your class type (FormA) using CType or DirectCast and then access the required method. Check:

For example: Replace p_FormInstance.subUpdateStatusBar(aList) with:

' Cast to Form1
Dim cast_Form As FormA = CType(p_FormInstance, FormA)
'  then you can call method
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

Jacques Bourgeois (James Burger)PresidentCommented:
Unless you have many calls to make to the designer, do not create variable when you have only one call to make. The system needs to work in order to create a variable and destroy it afterward.

Go directly to the Designer from with code like the following:

DirectCast(Me.Parent.Parent, Designer).subUpdateStatusBar(aList)

Me is the Form inside the Panel
Me.Parent is the Panel
Me.Parent.Parent is the Parent of the Panel, that is your Designer

Note that I use DirectCast instead of CType. CType is not a cast, it is a type conversion. It works but requires more overhead than DirectCast that simply works directly with the pointer to the form.
Peter AllenAuthor Commented:

Using DirectCast with your example worked like a charm.  I have one question though...

I have the following code:

Private Sub subUpdateFormPanel()

        Dim f_PanelForm As New frmDataGridViewProject_Editor
        f_PanelForm.TopLevel = False
        f_PanelForm.Parent = Me
        f_PanelForm.p_sFormRecordEditState = "View"
        f_PanelForm.p_fParentForm = Me.ParentForm

    End Sub

Which defines the Form I am opening in the Panel.  The Editor form calls the StatusBar Subroutine to update the StatusBar on the Designer Main Form (which is not the MIDI container, but just another form in the application):

        Call DirectCast(Me.Parent.Parent.Parent.Parent, frmDataGridViewProject_Designer).subUpdateFormStatusBar(aStatusBarList)

Worked, but if I want to refer to more subroutines on the Designer form should I store this reference in one variable as the form is opened?  Once the form closes the variable goes away.

So I thought I could do something like:

Dim objName as new Object
objName = Me.Parent.Parent.Parent.Parent
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Did my comments not apply to your situation?...
Jacques Bourgeois (James Burger)PresidentCommented:

Your comment is not a very good way to work, even it if applies. It assumes that the form will always be the main form or the startup form. If for some reasons in the future (and these things happen during the life of an application) Peter finds out that he needs to start in another form or start in a Main method in order to initialize a few things at the start of the application or to trap errors globally, it will stop working. The DirectCast approach will work in all situations.

I always think with maintenance in mind when I code.



Do not call New on a variable when you assign it an already existing object. New create an object in memory. In your 2 lines, you first create an object (job for the system) and then the line right after you assign another object to the variable, so the system has to destroy the object that you have just created and never used. You use New only when you need to create a brand new object.

And try as much as possible not to us late binding (variables of type Object). It is a pain to use (you need to cast all the time), you do not have IntelliSense, the compiler is not able to detect errors and they have an impact on performance because the checks usually done by the compiler need to be done at runtime. Be specific when you know the type of an object.

And in .NET, when you already have the object at the point of declaration, you can do the assignment on the same line as the declaration.

I would rather go for something such as the following:
Dim designerForm as frmDataGridViewProject_Designer = DirectCast(Me.Parent.Parent.Parent.Parent, frmDataGridViewProject_Designer)

Open in new window

Another approach would be to add a constructor to you panel form and pass the designer to that constructor:
Private designerFormDesigner As frmDataGridViewProject_Designer
Public Sub New(designer As frmDataGridViewProject_Designer )
    designerForm = designer
End Sub

Open in new window

When you create the panel form, initialize this way (I understand that you instantiate it in the Panel):
Dim f_PanelForm As New frmDataGridViewProject_Editor(DirectCast(Me.ParentForm,frmDataGridViewProject_Designer)

Open in new window

From then on, no matter which of the 2 techniques you use, when you need to call a method on the designer form:

Open in new window

Not seeing all your code, I might have used the wrong identifiers of variables in some places, so you might have to change a name here and there.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
"I always think with maintenance in mind when I code."

Haha! sir are kidding right?  How can you make that statement and then a couple lines later recommend using "Me.Parent.Parent.Parent.Parent"?!

That suffers the exact same problem that you cited for my suggestion:

    "If for some reasons in the future (and these things happen during the life of an application) Peter finds out that he needs to start in another form or start in a Main method in order to initialize a few things at the start of the application or to trap errors globally, it will stop working."

If the container hierarchy changes then you have to figure out another mess to place in there instead.

Instead of using a TIGHTLY COUPLED solution (which passes specific types of references), I'd recommend a LOOSELY COUPLED approach.  Make your "embedded form" RAISE A CUSTOM EVENT that passes out the ArrayList.  The Designer form will Subscribe to that custom event at the embedded forms creation time.  Now, whenever that event is received, the Designer form can call whatever method it wants directly.  References don't need to be passed and it doesn't matter if the start form or container hierarchy changes.
Jacques Bourgeois (James Burger)PresidentCommented:

It was not "a couple lines later", but a couple lines earlier. And that makes a difference. As a trainer, I always try to adapt my answers to the level of the student who asks the question. The best answer is not always the best one to give. If the student is not to the level to understand the best solution, give him a solution he can understand. Later on, as he evolves as a programmer, you will teach him better ways to do things.

I do the same here on the Exchange.

Not knowing Peter's level through the simple code in his question, I went first for the simplest solution.

Then I answered to you, knowing that you are not a beginner.

And seeing that Peter was a little more advanced than what showed up in his first post and having got precisions on his needs, I went with a more advanced answer and a better solution.
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Fair enough...

Here's a simplified example of how the custom event can be implemented:
Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim f2 As New Form2
        AddHandler f2.Status, AddressOf f2_Status
        f2.TopLevel = False
        f2.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        f2.Dock = DockStyle.Fill
    End Sub

    Private Sub f2_Status(values() As String)
        If values.Length >= 3 Then
            ToolStripStatusLabel1.Text = values(0)
            ToolStripStatusLabel2.Text = values(1)
            ToolStripStatusLabel3.Text = values(2)
        End If
    End Sub

End Class

Public Class Form2

    Public Event Status(ByVal values() As String)

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        RaiseEvent Status(New String() {"cat", "dog", "fish"})
    End Sub

End Class

Open in new window

*Note that the custom event can pass out any type(s) that you choose, and that you can use RaiseEvent in response to code instead of user interaction.
Peter AllenAuthor Commented:
The feedback is Great.  Thank you everyone.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.