I wrote a Window Application which has two different parent-forms (form1, and form2). Each form has several child forms. After I login it opens form1. Now I have a button (called switch to form2) on form1, which switch to form2. Now I need to close form1 after opening form2. I need to same thing from form2 to form1.
What would be the best way to handle this.
I tried something like below by adding this code to close form under form load of each forms, but I am getting the following exception.
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Additional information: Collection was modified; enumeration operation may not execute.
Can you please suggest me to handle this problem?
Form 1
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
For Each frm As Form In Application.OpenForms
If frm.Name.ToLower = "form2" Then
frm.Close()
End If
Next
End Sub
Form 2
Private Sub Form2_Load(sender As Object, e As System.EventArgs) Handles Me.Load
For Each frm As Form In Application.OpenForms
If frm.Name.ToLower = "form1" Then
frm.Close()
End If
Next
End Sub
I suppose you are responsible for creating your forms.
If so, I would overload the constructor of each of the forms to take a parameter of the type of the other form and close it there.
For your Form1 it would be :
Public Sub New(form2 As Form2)
InitializeComponent()
'and the rest of your initialization code
If form2 IsNot Nothing Then
form2.Close()
End If
End Sub
Vice versa for the constructor of Form2.
It doesn't even have to be so specialized like above. You could always generalize it to take an object of the type Form as a parameter.
why not use Form1.Hide()?
that way you can still access the other form while it is not visible.
I hope this helps.
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 am trying to create a customized form class (CustomBorderlessForm) in VB.NET.
My Progress So Far
I created a new Class and named it CustomBorderlessForm.vb
I then proceeded to write the following code:
CustomBorderlessForm.vb
Public Class CustomBorderlessForm
Inherits Form
Dim _form As Form = Nothing
Public Sub New(form As Form)
_form = form
MsgBox("Testing: New()")
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
MsgBox("Testing OnMouseMove()")
End Sub
End Class
Form1.vb
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
End Sub
End Class
Results of progress
A message box displays "Testing: New()" on load
Nothing shows on mouse move
As you can see, my problem lies with the events
Questions
Is it possible to create a form object and use that instead of the pre-populating form?
If so, can I give this form custom properties, such as, a border and some boolean values (shadow...etc), just like any other custom object/class?
What am I doing wrong in my current approach?
Why isn't the OnMouseMove being overridden?
Am I initialising the class wrong?
Can it even be done this way?
After creating a form you also need to show it. Change your logic to:
Dim form As New CustomBorderlessForm(Me)
form.Show()
Before you do that, I'd recommend changing from MsgBox to Console.WriteLine(), otherwise you can run into a fun/frustrating little cat and mouse game.
EDIT
Based on the comments, if, from VS you did a "Add New, Windows Form" you can just right-click the project, select property and on the Application tab change the Startup object to your new form. VS only allows you to do this with forms it creates for you (by default, more on this later).
If you wrote that file by hand (which is absolutely fine) you can perform the Show() like I did above and call Me.Hide() to hide the "parent" form. Unfortunately the Load event is fired before the Show event so if you place this in Form1_Load() it won't work. Instead you can use the Shown event like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
form.Show()
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Hide()
End Sub
Another option has to do with "Application framework". You can read about it here however it basically handles application events that other languages have to manually implement. If you go into your project properties you can uncheck the "Enable application framework" checkbox. This will give you more option in the "Startup object" dropdown. If you add the following code to your project one of the items in the Startup object dropdown menu should now be "Loader"
Public Module Loader
<STAThread()>
Public Sub Main()
Dim form As New CustomBorderlessForm(Nothing)
form.ShowDialog()
End Sub
End Module
You'll notice that the above bypasses Form1 completely. Also, instead of Show() I'm using ShowDialog() because otherwise the form shows and then the program ends.
Is there any way to do the following, other than hiding then closing the hidden form later?
Mainform opens SecondForm as show dialog, i need to Open ThirdForm from SecondForm while closing SecondForm while keeping third form acting as "showdialog" on the MainForm?
When you show SecondForm(), pass in MainForm() as the owner to ShowDialog():
Public Class MainForm
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sf As New SecondForm
If sf.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
' ... do some processing in here ...
End If
End Sub
End Class
Now, in SecondForm(), you can then set the owner of ThirdForm() to that of SecondForm():
Public Class SecondForm
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Hide()
Dim tf As New ThirdForm
tf.ShowDialog(Me.Owner)
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
End Class
You could simply open the third form from the main form as soon as the second form returns a dialog result
You also might want to look at MDI this gives you more control over what the user can and can't do.
After trying Idle_mind suggestion it was still giving me problems going back and forth between forms continously showing them as .showdialog. I solved my problem just like tinstaafl suggested. I wish i would have got his message before a couple hours of trying different methods before coming up with this one.
When i close each form, i set a boolean flag in the main form. then i call a sub that is in the main form to show the next form as showdialog from the main form. i use the flag which triggers logic in the form im loading whether or not to bind data from datatable so i can edit it.
sorry with all those forms i know it gets confusing. to sum it up, close the dialog form (me.close), set flag so calling code knows what to do once the showdialog code is satisfied.
how do i close my form after opening the next form (VB.net Windows form) like the Next button
I tried Form2.show() it shows form2 but does not close the form1 and if i type me.close(), the entire project stops
If you just want Form2 to be Visible you can hide Form1 when you show Form2, then show it Form1 again when you close Form2. What is happening is that once you close Form1 your program will exit see below edit.
Something like this.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim frm2 As New Form2
AddHandler frm2.FormClosed, AddressOf Form2Closing
frm2.Show()
Me.Hide()
End Sub
Private Sub Form2Closing(sender As Object, e As FormClosedEventArgs)
Me.Show()
RemoveHandler DirectCast(sender, Form2).FormClosed, AddressOf Form2Closing
End Sub
If you just are wanting to Close Form1 and not go back to it once Form2 is open, you can change your project settings from When startup form closes(which is the default) to When last form closes then you can close your first form without closing your application.
You have to specify what to close:
Form1.Close()
You better not close your form after opening another one from it, unless you want that other one also closed. Otherwise it will cause ownership and visibility side effects, which you really don't want to deal with in the long run.
This is exactly why me.close() on your main form stops your project. You just have consider paradigms Microsoft put into a Winforms application. If you don't, you are guaranteed to get in trouble.
Instead, a wizard control is what you are probably looking for.
I've got a fairly simple question (I think) on passing variables between forms using Visual Basic.
I've got a program with 2 forms (Form1 and Form2). Form1 has 3 radio buttons, which the user has to select one of and then loads Form2.
Now I've made it so that if radiobutton1 is picked, the Public Variable "radio_select" will equal "radiobutton1", if radiobutton2 is picked, "radio_select" will equal "radiobutton2".
But whenever I try call "radio_select" in my second form, it comes up blank. Why could this be? And how can I fix it.
I've tried using if form1.radiobutton1.checked = true but I keep getting the first radiobutton, regardless of the radio button I've selected.
I think the form is being unloaded, or there is an issue somewhere there, as it appears none of the variables get passed to the second form, once it has been initialized. Also note, the first form is hidden Me.Hide() when the second form is called.
Have you considered a slight re-design whereby you create a property on Form2 called RadioSelect and then set this from Form1 before showing Form2:
Class Form2
Public Property RadioSelect As String
...
End Class
...
Dim f2 as new Form2()
f2.RadioSelect = "radiobutton2"
f2.Show() ' Or f2.ShowDialog()
This gets you away from an unnecessary public variable and should also ensure Form2 can see what it needs from Form1, or whoever calls it.
Edit:
The following works for me:
Public Class Form1
Public Test As String
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Test = "I'm Here"
Me.Hide()
Form2.ShowDialog()
End Sub
End Class
Public Class Form2
Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Text = Form1.Test
End Sub
End Class