VB.NET Calling forms by Variable - vb.net

I'm playing around in vb.net and would like to create a menu for my application. The application has an Main which is the MDI Parent and then has the sub forms that open up as the user browses the menu structure. I would like to track which form the user came from so that when they close their current form, it opens up the previous form they had open.
What I have so far is a public variable "FormTracking" which is a list of Form. The open form function works fine, but when they close the form and it calls the "OpenPreviousForm" function it fails as the previous form has been closed/disposed. How can i create a new instance of the form as calling "NEW" doesn't seem to work
Public FormTracking As New List(Of Form)
Public Sub OpenForm(theNewForm As Object)
'First Declare the new form
Dim f As Form = DirectCast(theNewForm, Form)
'Set the Forms parent
f.MdiParent = frmMain2
'Add the form to the tracking
FormTracking.Add(theNewForm)
'Show the form
f.Show()
End Sub
Public Sub OpenPreviousForm()
If modMenu.FormTracking.Count > 1 Then
Dim f As New Form
f = modMenu.FormTracking(modMenu.FormTracking.Count - 2)
'Set the Forms parent
f.MdiParent = frmMain2
'Remove the last item
modMenu.FormTracking.RemoveAt(modMenu.FormTracking.Count - 1)
'Show the form
f.Show()
Else
MessageBox.Show("Whoops, run out of forms.... ", "modMenu - OpenPreviousForm")
End If
End Sub
When opening a form it it calls:
modMenu.OpenForm(menupage_1)
me.close
And when closing a form, i try to call
modMenu.OpenPreviousForm()
The error i am getting when calling the above code is
"An unhandled exception of type 'System.ObjectDisposedExeption' occured in System.Windows.Forms.dll
Additional Information: Cannot access a disposed object
I understand i need to create the object again, but not sure how to using the functionality as above. Alternatively, if someone can present a better way of doing an application menu, please feel free to let me know.
Cheers

Use Me.Hide instead of Me.Close so you do not dispose the form.

Related

Tabbing on Form disappears when using Control.FromHandle

VB2010: I have a form that I display within a mapping application that supports their framework through .NET. So when the user clicks a button on a custom extension then my form will be displayed.
Private frm As New frmDesigner 'since this is a floating form
Public Overrides Sub OnClick()
Try
''display the form normally
'Dim frm As New frmDesigner
'frm.ShowDialog()
'display the modeless form and the form will always be on top of the main app.
If frm.IsDisposed Then frm = New frmDesigner 'To handle user closing form
If frm.Visible Then
frm.BringToFront()
Else
Dim appCtr As Control = Control.FromHandle(CType(MyApp.hWnd, IntPtr))
frm.Show(appCtr)
End If
Catch ex As Exception
DisplayException(ex)
End Try
End Sub
This works great and I have been using this approach for a couple years now. The problem that I am seeing now is that the tabbing through controls on the form does not work. Once the form appears I press on the Tab button and the cursor does not tab through the controls. I can set focus on a textbox through the mouse and then attempt to tab over to the next control but that doesn't work either.
If I display the form normally through frm.ShowDialog then the tabbing does work. Is there something I am missing here to make the tabbing work properly?

vb.net cannot access a disposed object when opening form

I have a program that we use to run different reports. Based on the menu option chosen, I open the same form that lists the reports based on the menu option.
(There are also different options and functionalities in the program, not just one form).
When clicking a menu option, I have the following bit of code
Private Sub ReportsToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ReportsToolStripMenuItem1.Click
FormLocation = "F_Legal"
FormName = "Legal"
PrepareForm(F_Select_Report)
End Sub 'ReportsToolStripMenuItem1_Click
Where F_Select_Report the form is that is opened.
Private Sub PrepareForm(formName As Form)
Cursor = Cursors.WaitCursor
For Each Form In Me.MdiChildren
Form.Close()
Next
formName.MdiParent = Me
formName.Height = Me.Height
formName.Width = Me.Width
formName.Show()
Cursor = Cursors.Arrow
End Sub 'PrepareForm
This bit is called, closing all other opened forms, and then open the form that is called.
This works fine on the first time I try and open a form, but on the second try, I get an error message saying
Cannot access a disposed object.
And then on the third try, it opens the form again.
How would I fix this up?
Thanks a lot
Form.Close implicitly calls Form.Dispose
So if the formName is an MdiChild it gets disposed in the For Each loop.
Then, on the next line your code attempts to assign to its MdiParent property and there the error occurs.
So you need to skip it when closing MDI children like this:
For Each Form In Me.MdiChildren
If Not Form Is formName Then Form.Close
Next
Given your code I think it is better to close the children before showing the F_Select_Report form. I.e. move the For Each loop as is to the top of the ReportsToolStripMenuItem1_Click handler.
Not sure if it is the best/nicest solution, but found a solution to this.
Instead of 1 Sub that does both closes all open forms, and then opens the new one, I split it out over 2 Subs.
Close all open ones
Private Sub CloseAllForms()
For Each Form In Me.MdiChildren
Form.Close()
Next
End Sub 'CloseAllForms
And then open the new form
Private Sub PrepareForm(formName As Form)
Cursor = Cursors.WaitCursor
Try
formName.MdiParent = Me
formName.Height = Me.Height
formName.Width = Me.Width
formName.Show()
Catch ex As Exception
MessageBox.Show("Error: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Cursor = Cursors.Arrow
End Sub 'PrepareForm
Now it works as needed.

Working with passed data between forms

Currently in my windows form, I have a few WinForms to work with. One WinForm acts as a main menu and is supposed to call another form as a secondary window on its own.
Private Sub btnMainGame_Click(sender As Object, e As EventArgs) Handles btnMainGame.Click
' This is the button to call up the main game controller. So simply hide this form aned then open the new form.
Dim frmController As New frmControllerScreen
frmController.Show()
Me.Hide() ' Happens on .Close as well
End Sub
The above code invokes another WinForm which is used to handle more options. When the user clicks on a particular button, a sub form is created again.
Dim OpenNewGameWindow As New frmGameConfig
OpenNewGameWindow.ShowDialog(Me)
Me.DialogResult = DialogResult.None ' Used to prevent the subform from closing the main form when it catches a dialog result.
Now in the frmGameConfig, the program is supposed to take data and pass it back to the form that called it.
Private Sub btnNewGameStartGame_Click(sender As Object, e As EventArgs) Handles btnNewGameStartGame.Click
' ... Skipped code...
frmControllerScreen.MasterQuestionList = QuestionList
frmControllerScreen.blnBankedTime = cbBankedTime.Checked
' ... Skipped code...
End Sub
However, when the frmController tries to reference MasterQuestionList... it returns a nullreference error as if it was not set.
Here's where things get funny...
When I made this code, frmControllerScreen was actually the startup form. Now when I change this form back to frmMainMenu, I get NullReference errors constantly.
My question: How am I supposed to pass information from one form to the next form if it was instantiated from a parent form. (Note I even moved the declartion to Public as a "module-wide" variable... and nothing happens but the same result.) The same error happens even if I go ahead and declare frmController.MasterQuestionList as well.
Instead of trying to pass data back from the called form to the caller, you can reference the called form's controls from the calling code after .ShowDialog.
Dim OpenNewGameWindow As New frmGameConfig
If OpenNewGameWindow.ShowDialog() Then
MasterQuestionList = OpenNewGameWindow.QuestionList
blnBankedTime = OpenNewGameWindow.cbBankedTime.Checked
End If
In OpenGameWindow button click:
Private Sub btnNewGameStartGame_Click(sender As Object, e As EventArgs) Handles btnNewGameStartGame.Click
Me.DialogResult = True
End Sub

vb.net Closing multiple form and open another form

I have 2 forms open, my current form is in dialog box. Now I want to close that 2 forms and open another form.
Dim frmStg2 As New frmStageTwo
Dim frmStg1 As New frmStageOne
frmStg2.Show()
Me.Close()
frmStg1.Close()
But this code seems not working the frmStageOne is still open and showing frmStageTwo but I can't view that form.
This is what happen
You are trying to close a form instance that has not yet been opened.
When you use the New keyword you are declaring a new instance of an object (a Form in this case) which has it's own version of the base class's properties and fields.
In order to close an already existing instance of the form you can loop through the Application.OpenForms property.
For Each frm As Form In Application.OpenForms
If frm.GetType() Is GetType(frmStageOne) Then
frm.Close()
End If
Next
You could actually make it a method:
Public Sub CloseFormsOfType(ByVal TargetForm As Form)
For Each frm As Form In Application.OpenForms
If frm.GetType() Is TargetForm.GetType() Then
frm.Close()
End If
Next
End Sub
...and just call:
CloseFormsOfType(frmStageOne)

Passing Values from modal form to parent form vb.net

I am trying to pass information to parent form from modal form in vb.net winforms application.
1.) I created a copy of a form and displayed it using following code.
dim f=new frmParent()
f.show()
2.) Depending on conditions a button on frmParent opens a modal child form and asks for some informations. I used following code for that:
dim f = new ChildForm()
f.showDialog()
Both code works fine. When user press saves in child form i need to close childForm and use the user types values in parent form. I know how to close the childform but not sure how to pass info from childform to parent form.
Have a public property on your childForm
Public Property MyData As MyType
Then when you show the form you can do
dim f as new ChildForm()
If f.showDialog = DialogResult.OK Then
Data = f.MyData()
End if
If you need to allow them to be able to edit that data again then you might also want to consider passing in the Data to the constructor of the dialog.