Reference to a Form stored in a Public Property

Posted on 2012-04-11
Last Modified: 2012-04-16

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.
Question by:Peter Allen
  • 4
  • 3
  • 2
  • +2
LVL 15

Expert Comment

by:David L. Hansen
ID: 37834562
Take a look at "my.forms...." you can usually reference your forms directly using that.
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 37835182
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:

LVL 35

Assisted Solution

by:Miguel Oz
Miguel Oz earned 25 total points
ID: 37835184
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
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

LVL 40

Assisted Solution

by:Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger) earned 250 total points
ID: 37836516
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.

Author Comment

by:Peter Allen
ID: 37837079

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
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 37837289
Did my comments not apply to your situation?...
LVL 40

Accepted Solution

Jacques Bourgeois (James Burger) earned 250 total points
ID: 37838371

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.
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 225 total points
ID: 37838668
"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.
LVL 40

Assisted Solution

by:Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger) earned 250 total points
ID: 37838845

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.
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 225 total points
ID: 37838987
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.

Author Closing Comment

by:Peter Allen
ID: 37851080
The feedback is Great.  Thank you everyone.

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question