Search code examples
vb.netwinformsvb6vb6-migrationselectedindex

Reference to a non-shared member requires reference


I am updating some code from a vb6 application to VB.NET.

I have a problem that occurs when I try to open a form from the main form.

It calls this function:

Public Sub optDrawSafeFile_CheckedChanged(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles optDrawSafeFile.CheckedChanged
    If eventSender.Checked Then
        '--------------------------------------------------------------------------------
        ' JRL 11-03-06
        ' change the enables

        UpdateGUI((False))
        cboProject.SelectedIndex = frmMain.cboProjects.SelectedIndex
        SelectJob()
    End If
End Sub

And when it goes to execute this line:

cboProject.SelectedIndex = frmMain.cboProjects.SelectedIndex

It blows up and says this:

enter image description here

frmMain is declared like this:

enter image description here

How can I fix this error?

TL;DR

It is described in more detail in this video.


Solution

  • Short answer: change frmMain to My.Forms.frmMain.

    cboProject.SelectedIndex = My.Forms.frmMain.cboProjects.SelectedIndex
    

    Long answer:

    In VB6, referencing a form by its name allowed you to access it both as a class and an instance of that class. The instance that you access in this manner is called the default instance. This is not possible in VB.NET. However, VB.NET includes a dynamically generated class, My.Forms, that provides functionality similar to that of default instances.

    See http://msdn.microsoft.com/en-us/library/ms379610%28v=vs.80%29.aspx#vbmy_topic3 for more information about My.Forms and the "My" namespace.

    A better and more object-oriented way to handle this, however, would be to pass the instance of the main form to the constructor of the frmAddMethod form and store it in an instance field.

    So, within the class definition in frmAddMethod.vb:

    Sub New(ByVal mainForm As frmMain)
         _mainForm = mainForm
    End Sub
    
    Private _mainForm as frmMain
    

    And when you create the frmAddMethod instance from frmMain, pass in "Me" to the constructor:

    Dim addMethodForm as new frmAddMethod(Me)
    

    "Me" is the instance of the class from which a non-shared class method was called.

    This will allow you to use the _mainForm class field to access the instance of the main form from non-shared methods of frmAddMethod.

    *Edited to recommend My.Forms instead of DefInstance per Plutonix's comment.