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
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.
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.
Related
I am getting a an Null reference exception when trying to add an item to a listbox in a different form.
This is my error at run time.
An unhandled exception of type 'System.NullReferenceException'
occurred in ... Additional information: Object reference not set to an
instance of an object.
I am trying to connect the Mainform by initializing it at the top of the class of the secondForm. after I have my data i want to add it to a listbox it the mainform.
Public Class FormHairdresser //The second form
Dim varMainForm As FormMain //connecting the forms ?
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
hairdresser = HairdresserChoices(HairdresserID) // get the data
varMainForm.lstListBox.Items.Add(hairdresser) //Run time error breaks here.
All i had to to was write the form name instead of ininalised variable.
FormMain.lstListbox.Items.Add("item")
Instead of
Dim varMainForm As FormMain
varMainForm.ListBox.Items.Add("item")
You cannot simply create a new instance of your main form (as has been suggested and expect that to work, you need an actual reference to the mainform that you have created. To help you see the logic involved;
Create a new Winforms project. In the default Form1 add a textbox and a button.
Now add a new form to this application (you can leave it with its default name of Form2. To this form add a TextBox (call it myTextBox) and a button.
Now go back to your first form and doubleclick the button to access the click handler in code. Add the following:
Dim frm as New Form2
frm.Show
Press f5 and click the button and you'll see a new form 2. So far so good.
Now open up the code for Form2 and add the following code so that it ends up looking like this:
Public Class Form2
Private frm As Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
frm.TextBox1.Text = myTextBox.text
End Sub
End Class
build, press f5 and click the button on form1, in the new form2 enter some text in the text box and click the button, you get your null reference exception. The reason you get this is because at the moment the private field frm inForm2 refers to Nothing.
Now open up the code in Form2 and add a constructor and the following code so that it ends up looking like this:
Public Class Form2
Private frm As Form1
Public Sub New(byval frm1 As Form1)
'first we should make sure that we have a parameter to play with
If Not IsNothing(frm1) Then
frm = DirectCast(frm1,Form1)
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
frm.TextBox1.Text = myTextBox.text
End Sub
End Class
Finally go back to your first forms buttonclick handler and change the code slightly so that it looks like this;
Dim frm as New Form2(Me)
frm.Show
Build and run your application, now when you enter text into the textbox in form2 and click the button it will appear in the textbox in Form1.
The reason why this happens is because you have passed an actual reference to the form1 that was originally created when the application started to form2. By casting that reference to your private field used to represent form1 in form2 you can then use it to properly refer to things on form1. This is a very simple concept but one which you need to learn before you will make progress programming.
the Problem is with your initialization of the formmain.with out proper initialization the object you are creating is nothing other than Null.To avoid this we use New Operator.The New operator can often be used to create the instance when you declare it.
So the initialization will look like
Dim varMainForm As New FormMain
Hope this Helps.For more Reference Object Initialization Errors
update:
Dim varMainForm As FormMain //connecting the forms ?
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
hairdresser = HairdresserChoices(HairdresserID) // get the data
varMainForm = New FormMain
varMainForm.lstListBox.Items.Add(hairdresser) //Run time error breaks here.
Try This.
Public Class FormHairdresser //The second form
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
Dim varMainForm As FormMain
hairdresser = HairdresserChoices(HairdresserID)
varMainForm.lstListBox.Items.Add(hairdresser)
i have form1 to enter movies details
in this form1 i have a textbox called NVideosGenres
through this textbox i can open the form2 with a space
the form2 contains 5 combobox to let the users choose the genres if there is more then one
when user choose the genres they will be applied to a textbox in the same form like this way
for example i choose from three combobox
action - war - western
so now i have a problem because i know that to pass value i should do this
Videos.NVideosGenres.text = me.FinalGenres.text
me.close()
when i click on the button the form2 will close but the data don't pass to NVideosGenres in the form1
any help??
There are many, many ways to do this. One of the easiest ways would be to create a property on Form2 that holds a reference to your main calling form. Then you can set the values of the textboxes (or whatever) directly from Form2. This is definitely not the best way to do it, but it certainly is quick and easy.
Private Sub btnShowForm2_Click(sender As System.Object, e As System.EventArgs) Handles btnShowForm2.Click
'Create a new instance of Form2 (called frmDetail in this example).
Dim frm2 As New frmDetail()
'Set the MyParentForm property of Form2 to this form.
frm2.MyParentForm = Me
'Show the form.
frm2.ShowDialog()
End Sub
Now in Form2, when you click the "OK" button to close the form, you can use the property that references your parent form to set the values directly.
' Property to hold a reference to the calling form.
Private mParentForm As frmMain
Public Property MyParentForm() As frmMain
Get
Return mParentForm
End Get
Set(ByVal value As frmMain)
mParentForm = value
End Set
End Property
' When I click the OK button, I will store the value of my various textboxes to properties.
Private Sub btnOK_Click(sender As System.Object, e As System.EventArgs) Handles btnOK.Click
'Set the value of the Genre textbox on the parent form to the value
'of the textbox on my current form.
MyParentForm.txtGenre.Text = txtGenre.Text
Me.Hide()
End Sub
I encounter the following scenarios when I try to use 2 forms. My workflow is as follows:
(1) Load Form1.
(2) A click on button1 on Form1 closes Form1 and opens Form2.
Solution A: If I use the following code:
Dim oForm As New Form2
oForm.ShowDialog()
Me.Close()
Then Form1 will be under Form2 (Form1 still opens).
Solution B: If I use the following code:
Dim oForm As New Form2
oForm.Show()
Me.Close()
Then Form1 closes and Form2 opens, but Form1 is not on the top layer.
I have looked through the solutions for this, most propose solution B, but for me, both solutions won't work the way I want. Can anybody tell me the reason?
Try
Dim oForm as New Form2
oForm.Show()
and on Load event of form2
Form1.Hide()
Use form.bringtofront() if you want to see the opening Form in the front, I m little confused though about what you are trying to do
Try doing it this way:
Dim oForm As New Form2()
Me.Hide()
oForm.ShowDialog()
Me.Close()
I suspect your are building a log-in dialogue... if so, or something similar, try this..
Open your main form first... (Form 2), have form2 showdialog (modally) form1... this will put form1 on top of form2.
Add a property to form 1, that gets set depending on what happens there.. sucessfull login for instance.
Close form 1 from its own methods... (after successful authentication), set the property before closing.
On form2, read this property of form1, and then dispose form1, and decide what to do... if unsuccessful login, show the login form again, end app. If successful, just gracefully exit out of the method that showed form1. Your form 2 is now the only form open.
Start with Form2
Form2_load
dim f1 as new form1
f1.showdialog
if f1.someproperty = somevalue then
' do something here, for instance, pop the form again, if you did not get what you were lookign for...
end if
'gracefully let the function end and form2 is now the only open form..
'dispose of form1. form1's close call does not dispose it, because it was opened modally. (showdialog)
f1.dispose
f1 = nothing
in form1, depending on what you are doing, set the custom property and call me.close, this will exit the form, and run the next code in form2.
try this:
Dim oForm As New Form2
oForm.Show()
Me.Visible = False
You would to close your first form and this close your program. If you set him on invisible, he is not closed.
Just go to form2 and write the Form1.hide() . I tried to close form1 but it closed my whole program.
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Form1.Hide()
End Sub
End Class
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
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.
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.
I have two forms, form 1 and form 2 (windows application). How can i access and check a checkbox in form 1 from form 2. Initially i tried calling the form name and then the control like form1.chkCanada.checked = true, it did not work. And then i added a property in form 1
Public Property abc As Boolean
Get
Return chkCanadianStmtInd.Checked
End Get
Set(value As Boolean)
chkCanadianStmtInd.Checked = value
End Set
End Property
and then in form 2
Dim frm As New frm1
frm.abc = True 'Checked
And it still doesnt work. Am i missing anything here?
Alternatively you can pass a handle of form1 to form2 constructor
Form1:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim _form2 As New Form2(Me)
_form2.Show()
End Sub
End Class
Form2:
Public Class Form2
Public Sub New(ByVal _form1 As Form1)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_form1.CheckBox1.Checked = True
End Sub
End Class
Consolidating comments here:
In order to access controls on a form that shows another form to the user you have two options, if no interaction is needed with the first form while the second form is active you can use showdialog and do all of your logic after the second form has closed, if you ned to maintain the ability to interact with the first form while the second is still open then you need to use custom events.
Showdialog:
The simpler of the two options is to switch your form.show() function calls to form.showdialog(). This effectively tells the first form that it should stop processing at the form.showdialog() line and wait for the child form to close before proceeding. Once the second form is closed the first form will pick up where it left off and that would be where any processing that relies on the values of the second form would take place.
Custom Events:
If you want to allow the user to interact with both the first and second forms at the same time then you will need to use custom events. In order to do this you will need three things. The custom event, a raiseevent call and an event handler.
So in your Form2 class you will need to declare the custom event. In this case since you are trying to check(or uncheck I assume) a box your custom event declaration will look like:
public event ChangeCheckedValue(byref state as boolean)
Now on your button click event you will need to raise the event to the handler on Form1:
RaiseEvent ChangeCheckedValue(booleanValue)
Now that those statements are in place you will need to changed your form2 object that is being shown by Form1. What I normally do is make Form2 a form wide variable on Form1 and declare it like:
private withevents frm as Form2
Once you have the frm variable in your Form1 class you can add a handler for the ChangeCheckedValue event:
protected sub HandleCheckChanged(byref bln as boolean) handles frm.ChangeCheckedValue
'Set the checked state of your checkbox.
End sub
Once you have all that set up you should see what you expect.