Question

It takes two forms to be able to enter all the info on a particular transaction. I want to be able to flip back and forth between these two forms retaining what was entered on each until the 'Save' button is clicked.

I think I should be able to use Form2.Show, Me.Hide and then Form1.Show, Me.Hide. The first time I go to Form2 it goes thru the Form2 load event (that’s reasonable) but any knowledge of the control contents on Form1 have been lost. Even though Form1 is hidden (and not closed) the contents of its controls are gone. Why?

The second time I go to Form2 the load event does not fire because Form2 is hidden and at this point all the Form1 control contents are available. So, in flipping back and forth between Form1 and Form2 it works as I want it to after I go to Form2 the second time. But, I need it to work the first time and every time.

For days I’ve been trying to understand this. I’ve commented out nearly every line of code, stepped thru code, googled till I’m blue in the face (there has been a lot written about this), and I still can’t figure out why this behavior occurs.

Can anyone explain this phenomenon? Or better yet tell me what I need to do to make this work.

I have this code behind the Form1 button that goes to Form2

If Form2 Is Nothing Then
    Dim Form2 As New Form2
End If
Form2.Show()
Me.Hide()

And this code behind the Form2 button to return to Form1

Form1.Show
Me.Hide
Was it helpful?

Solution

This is all you are probably missing:

Class Form1
     Private f2 As Form2       ' this is Form1's reference to the
                               ' form2 instance

Later when you click to go to form2, your original code just needs a small tweak:

If f2 Is Nothing Then
    f2 = New Form2(Me)             ' set declared variable to new instance   
End If
F2.Show()
Me.Hide()

In this case Form1 is passing the reference using the trick you were shown before using the constructor:

Sub New(frm As Form1)         ' this is in Form2 only
   f1 = frm               
End Sub

You dont need this in Form1 because he/it is creating his own f2 object reference.

The main problem in your original code, was: Dim Form2 As New Form2. You are creating a new Form2 each time (I suspect that resides in an event or sub). Those new instances can't know the control values in the previous instances. Declaring F1 or F2 as shown gives it module/form level Scope.

Dim declares a variable and its Type. f1 is of Type Form1. It does not create an object if it is an object variable

New creates an instance of an object Type (reference types). This directly relates to the Sub New method in the class. When you use New, Sub New is called so anything special that is needed can take place there. Value types like Integer do not need to be created or instanced, only declared.

Where you declare (Dim) a variable determines its Scope. If you do this in a Sub, the variable or object only exists in that sub. if you do it at the form/class level, it has Form/Class level scope.

OTHER TIPS

I would try something like this. Display the 2 forms modally using the ShowDialog method.

In each form, create a property (call it "OtherForm") which points to an instance of the other form.

Continue the loop by setting the DialogResult of either form to Windows.Forms.DialogResult.Yes

Exit the loop by setting the DialogResult of either form to Windows.Forms.DialogResult.No

This will execute each forms load event each time it is displayed.

So call this from a button click event procedure on your so-called Form0.

Dim Form1 As New Form1
Dim Form2 As New Form2
Dim sFormToShow As String = "Form1"

Form1.OtherForm = Form2
Form1.DialogResult = Windows.Forms.DialogResult.Yes

Form2.OtherForm = Form1
Form2.DialogResult = Windows.Forms.DialogResult.Yes

Do

    If sFormToShow = "Form1" Then
        Form1.ShowDialog()
    ElseIf sFormToShow = "Form2" Then
        Form2.ShowDialog()
    End If

    sFormToShow = IIf(sFormToShow = "Form1", "Form2", "Form1")

Loop While Form1.DialogResult = Windows.Forms.DialogResult.Yes AndAlso Form2.DialogResult = Windows.Forms.DialogResult.Yes

Add this property to Form1:

Private _myOtherForm As Form2

Public Property OtherForm() As Form2
    Get
        Return _myOtherForm
    End Get
    Set(ByVal value As Form2)
        _myOtherForm = value
    End Set
End Property

Add this property to Form2:

Private _myOtherForm As Form1

Public Property OtherForm() As Form1
    Get
        Return _myOtherForm
    End Get
    Set(ByVal value As Form1)
        _myOtherForm = value
    End Set
End Property

From each form, you will then be able to access all of the public properties and methods of the other form using the _myOtherForm variable.

If you were to call this from Form1, it will display the text in TextBox1 in Form2 and vice-versa:

MessageBox.Show(_myOtherForm.TextBox1.Text)

To close the current form, continue the loop and open the other form, add this to a button click event procedure:

Private Sub btnShowOtherForm_Click(sender As Object, e As EventArgs) Handles btnShowOtherForm.Click
    Me.DialogResult = Windows.Forms.DialogResult.Yes
    Me.Close()
End Sub

To close the current form, exit the loop and to cease showing any further forms, add this to a button click event procedure:

Private Sub btnStopShowingForms_Click(sender As Object, e As EventArgs) Handles btnStopShowingForms.Click
    Me.DialogResult = Windows.Forms.DialogResult.No
    Me.Close()
End Sub

These two procedures need to be added to each form.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top