Go Premium for a chance to win a PS4. Enter to Win


Reference to a Form stored in a Public Property

Posted on 2012-04-11
Medium Priority
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 86

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 36

Assisted Solution

by:Miguel Oz
Miguel Oz earned 100 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

LVL 40

Assisted Solution

by:Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger) earned 1000 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 86

Expert Comment

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

Accepted Solution

Jacques Bourgeois (James Burger) earned 1000 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 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 900 total points
ID: 37838668
"I always think with maintenance in mind when I code."

Haha!...you 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 1000 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 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 900 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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

This article explains how to create and use a custom WaterMark textbox class.  The custom WaterMark textbox class allows you to set the WaterMark Background Color and WaterMark text at design time.   IMAGE OF WATERMARKS STEPS Create VB …
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses
Course of the Month13 days, 8 hours left to enroll

963 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