Reference variables and objects elsewhere in a form

I am trying to pass an equipment object to a form object and then use that equipment object in a click event from a button on the form. But I don't know how to properly reference the equipment object within the button event.

I set up the new form instance using:

Public Sub New(ByRef thisEquip As classEquipment)
    Me.InitializeComponent()
    Me.Text = thisEquip.equipName & " Tests"
End Sub

and set up the button click event like this:

Private Sub btnUpdateAndClose_Click(sender As Object, e As EventArgs) Handles btnUpdateAndClose.Click
    Call updateTestList(thisEquip)
End Sub

But the 'thisEquip' object is not recognized. I think this is because the sender is the button and not the form itself. However, I don't know how to reference the equipment object from the form.


The Scope depends on where a variable is declared. You might have missed something skimming the link - each scope level summary includes the phrase in which it is declared.

Now look at your constructor:

Public Sub New(ByRef thisEquip As classEquipment)

thisEquip is declared as an argument to the constructor. Thus, it only exists in that procedure. The fact that the procedure is in a form or that thisEquip is mentioned in the form (or module or anything else) is incidental. While it is true that the constructor is special in several ways, in matters of Scope, it is just another procedure.

Form Level Scope

To save a reference to it for use elsewhere:

Public Class Form1
    ' declare a variable to hold the reference
    Private myEquip As classEquipment
    ' declare an array
    Private myImgs As Image()

    Public Sub New(ByRef thisEquip As classEquipment)
        InitializeComponent()
        ...
        myEquip = thisEquip         ' assign param to the var

        ' assign array of images to the Form level var
        ' via a temp array
        myImgs = New Image() {My.Resources.add, 
                              My.Resources.ballblack, My.Resources.ballblue,
                              My.Resources.ballgreen}
    End Sub

Declared at the form level, it has form/class level scope. You can now reference myEquip or myImgs anywhere in the form. Do Not Use Dim when merely assigning something to a form level object - it will create a new local, but identically named variable.


Other common scope levels:

Procedure Level Scope

Private myFoo as Int32

Private Sub DoSomething()
    Dim myBar As String 
    myBar = "Ziggy"
    ...
    Dim myFoo As Int32 = 7
End Sub

This is more often called local scope. I am using procedure level because it compares and contrasts better to the other terms.

myBar is declared in the DoSomething method, so it has procedure level scope - it only exists in that method. Trying to use it elsewhere will result in an error. This is similar to the constructor example above with the main difference being that the thisEquip object was passed as a parameter rather than declared locally.

This leads some to get confused: the Dim myFoo in the method declares (creates!) a new, local-only myFoo variable which has no relation to the Form/Class level variable of the same name. The local version shadows out the other. Part of the confusion for this seems to be that some think they need to (re) use Dim before they can use a variable. You do not.


Block Level Scope

Directly from MSDN:

If n < 1291 Then
    Dim cube As Integer
    cube = n ^ 3
End If

A fair number of VB statements create a block scope (For Each/Next, If/End If and Using/End Using). Variables declared inside a Block, have a scope limited to that block. Basically, (almost) anything which results in indentation creates a Block Scope.

Private Sub .....
    Dim cube As Int32

    If n < 1291 Then
       cube = n ^ 3
    End If

Now, cube can be used elsewhere in the procedure: its scope has been changed from Block to Local.

For more details, see MSDN:
- Scope In Visual Basic
- Value Types vs Reference Types