Take this example:
I have a LoginForm and when I enter my credentials into the text box and click Go it the directs me to my main HomeForm. On this event it stores the current user text from the User Textbox in the Login form in a Public Variable in the HomeForm called CurrentUser So my code is like this:
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
Home.CurrentUser = UsernameTextBox.text
End Sub
When I then try to access the information stored in the variable I am having no problems it's just that I want to know if the user closes the HomeForm will the variable still equal to the previous value before the user closed the Form. And if not how would you recommend on saving. I Don't want to be using stream readers/writers due to all the unnecessary text files.
Any help is greatly appreciated!
If you declare CurrentUser as Shared then it will keep the value even when the form is closed and then re-opened (assuming the whole application hasn't been closed):
Public Class HomeForm
Public Shared CurrentUser As String
End Class
Access it using the Forms name:
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
HomeForm.CurrentUser = UsernameTextBox.text
End Sub
*If you are looking at saving this value across application runs, then add a "CurrentUser" value in Project --> Properties --> Settings, then use code like:
Private Sub btnOK_Click(sender As System.Object, e As System.EventArgs) Handles btnOK.Click
My.Settings.CurrentUser = UsernameTextBox.text
My.Settings.Save()
End Sub
You can retrieve the value from anywhere using: My.Settings.CurrentUser
As long as you access the same instance of your HomeForm class, the variable values will still be there for you to access after the user has closed the form.
This applies to any fields or properties that do not access any of the inherited properties or methods of the Form class. Such methods by Form may depend on internal resources that are indeed freed upon closing or disposing of the form, while simple CLR properties will remain untouched for as long as the instance is within scope.
Dim onearray() As String
Dim i As Integer
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
Home.CurrentUser = UsernameTextBox.text
Home.CurrentUser = onearray(i)
i = i + 1
End Sub
It depends on how you are calling your form from the login form you described. Calling it with the show method will dispose the form after the user closes the form. Please see comments below for explanations and behavior this may cause.
According to MSDN
The Closing event occurs as the form is being closed. When a form is closed, all resources created within the object are released and the form is disposed.
Based on further examination it is possible to read a simple variable even if the form is disposed. However, in my opinion I would approach saving the needed data by passing in an object or variable as outlined below.
There are several ways you can persist or save the Current User information in order to safely access it later. Here is one.
Create a class called CurrentUser and give it basic public properties you can get and set.
Add a New Constructor to HomeForm and pass a byref argument reference of the new CurrentUser object.
Set or get any information needed from the CurrentUser object
When the form closes you will have the information needed from the CurrentUser object passed into the form. Ensure the scope of this object is avaliable to other parts of your as needed. (i.e make it a public property in the form that calls the Home form.)
dim ouser as new CurrentUser
dim frmHomeForm as new HomeForm(ouser)
frmHomeForm.show
msgbox(ouser.Name)
If you want to save the value after the user closes the application then you can add a setting in the Project Properties, and just refer to My.Settings.YourSettingName instead of using a variable to get and set the users login name.
You can use Settings (Click Prject -> Project Settings -> settings -> Add setting) if you want to access it another time when you open your program variables might not save all the time only in case how you will use them.
Related
I have a Window-Form 'caller' in vb.net containing a datagridview with a small overview table of certain objects, each with its own ID in the first column. Now, if a row is double clicked, i want to show a dialog 'edit', where one can edit many details of that row which i do not want in the overview table.
My approach is as follows: In the caller form i wrote this to call 'edit':
Private Sub dgdata_dbclick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dg_data.CellMouseDoubleClick
Dim f_edit As New edit
f_edit.ShowDialog(Me)
End Sub
That works fine.
However, in the called Form "edit" i need to check, which ID was selected and load this data from the database to edit it. I can access some data from the calling form 'caller' using e.g.
MsgBox(CType(Me.Owner, caller).Text)
to show the window title of 'caller'. However, i want to extract the currently selected ID in the datagridview or at least some variabhle containing it. In the caller form, this could be easily done by evaluating
dg_data.Item(0, selectedRow).Value.ToString
but i cannot access any relevant information in 'caller'. I have a public class with some global variables there but i cannot access them as well.
Probably my strategy to solve this problem is not the most clever approach? Basically, i want to open a very detailed edit window when someone clicks on a line in an overviewtable but simultaniously blocking the rest of the application as long as the edit window is open.
Thanks!
The idea is to pass the data to the second form. When you create an instance of the second form (my class is called Form2, yours is called edit) with the New keyword the Sub New is called on Form2.
Private Sub OpenEditDialog()
Dim f_edit As New Form2(32) '32 is the number you retrieve from your DataGridView
f_edit.ShowDialog(Me)
f_edit.Dispose()
End Sub
You pass the ID to Form2 and set a variable at Form level. You can then use the variable anywhere in Form2.
Public Class Form2
Private ID As Long
Public Sub New(SelectedID As Long)
InitializeComponent()
ID = SelectedID
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show(ID.ToString)
End Sub
End Class
You need to call InitializeComponent() so the controls will show up.
How do you usually get data into objects? You set a property or pass an argument to a method or constructor? Why should this be any different? Decide which you want to use and then write that code in your form. If it's required data, I would suggest a constructor. Just write this code in your form:
Public Sub New
and hit Enter. That will generate a little extra code automatically. You can then add a field to store the value, a parameter to the constructor and then assign the parameter to the field inside.
Thank you for pointing me to the correct route.
I solved it like this (which works fine and which is hopefully acceptable):
In the calling form:
Private Sub dgdata_dbclick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dg_data.CellMouseDoubleClick
Dim selectedRow As Integer = dg_data.CurrentCell.RowIndex
Dim f_edit As New edit
f_edit.edit(dg_data.Item(0, selectedRow).Value.ToString)
f_edit.ShowDialog(Me)
f_edit.Dispose()
End Sub
In the called form:
Public Sub edit(ByVal id As Long) 'Handles MyBase.Load
'Enter commands to prepare your form
End Sub
I'm trying to develop a search window that allows a user to fill in criteria, then click the search button. When the search button is clicked the results are returned in a DataGridView. When a result in the DataGridView is clicked, I'd like to pass the row number to another form that is already open.
I understand I can pass the result by creating a new instance of the form. I pass variables to my Search Window using the following method:
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
ST.Show()
End Sub
however I cannot call the form I want to pass the row value to because it is already open (its the main form). Is there a way to handle this? I'm struggling to find any information that doesn't call the form to open it whilst passing the data.
I can't reference Main_form.Main_DGV.CurrentCell as Visual Studio says it requires an Object Reference in order to do so.
Thanks in advance!
I'd recommend an event in your Search_Tool form that is raised when the user has found what they're looking for.
The main form is subscribed to that and can then access its datagrid.
Class Search_Tool
Inherits Form
Public Event SearchResultFound(resultId As Integer)
Private Sub OnUserClickedARowOrPressedAButtonOrWhatever()
RaiseEvent SearchResultFound(currentRow.Id)
End Sub
End Class
And in the main form.
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
AddHandler ST.SearchResultFound, Sub(result As Integer)
'handle your result id here.
MessageBox.Show("User selected row " & result)
End Sub
ST.Show()
End Sub
The advantage of this is that the SearchForm doesn't need to know what it's being used by. It's just there to give results which will make it easier to reuse later.
When press F5 to compile a project, there are no errors or warnings but the form won't show up. What's up?
Every time that you try to run your code, it starts by creating an instance of frmMain, your default form and the one that is shown at application startup.
When this form is created, it automatically instantiates an instance of Form3 because you instantiate a variable of that type called modifyForm at the top of this form's code file:
Dim modifyForm As New Form3 'modify student
The problem is that, when the runtime goes to instantiate an object of type Form3, it gets called right back to where it was because of this statement at the top of the Form3 code file:
Dim frmMain As New frmMain
Rinse, lather, and repeat. Your code turns into an infinite loop, trying to instantiate an instance of frmMain, which tries to instantiate an instance of Form3, which tries to instantiate an instance of frmMain, ad nauseum. Eventually, this will overflow your available memory and cause a StackOverflowException.
It's important to note that all of this happens before the default instance of frmMain is even shown, because these variables are declared outside of any methods in your code. Because the computer never can escape this infinite loop, it never gets a chance to move on and actually display your form.
And the moment you've all been reading so patiently for:
Fix it by removing the declaration of frmMain at the top of the Form3 code file. I don't know what that's there for, anyway.
EDIT: Hopefully, I can clear up a little confusion regarding passing values between forms. Upon further study of your code, my instincts tell me that the best solution for you is to overload the constructor for Form3 to accept the calling form (the existing instance of frmMain) as an argument. This will allow you to access all of the public members of frmMain from within your Form3 class.
Here's a rough sketch of how you might do this in your code:
Public Class frmMain
''#The private data field that stores the shared data
Private _mySharedData As String = "This is the data I want to share across forms."
''#A public property to expose your shared data
''#that can be accessed by your Form3 object
Public Property MySharedData As String
Get
Return _mySharedData
End Get
Set(ByVal value As String)
_mySharedData = value
End Set
End Property
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''#Do all of your other stuff here...
''#Create a new instance of Form3, specifying this form as its caller
Dim otherForm As New Form3(Me)
''#Show the new instance of Form3
otherForm.Show()
End Sub
End Class
Public Class Form3
''#The private field that holds the reference to the main form
''#that you want to be able to access data from
Private myMainForm As frmMain
Public Sub New(ByVal callingForm As frmMain)
InitializeComponent()
''#Save the reference to the calling form so you can use it later
myMainForm = callingForm
End Sub
Private Sub Form3_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''#Access anything that you need from the main form
MessageBox.Show(myMainForm.MySharedData)
End Sub
End Class
As you can see, frmMain exposes a public property (backed by a correspondingly-named private variable) called MySharedData. This can be absolutely anything you want, and you can have as many of these as you want.
Also notice that how the constructor (the New method) for Form3 accepts an instance of frmMain as an argument. Whenever you create a new Form3 object from frmMain, you just specify Me, which indicates that you want to pass the current instance of frmMain. In the constructor method, Form3 stores that reference to its calling form away, and you can use this reference any time you like in Form3's code to access the public properties exposed by frmMain.
In VS2010 menu, go to Build -> Configuration Manager, does your project have the checkbox in the "Build" column enabled?
If it's project upgraded from an older Visual Studio version it may be that it is not targeting .NET Framework 4.0. In that case you should change it as explained here.
To analyze the problem press F8 (or F10, depends on your default keyboard settings) to step into the code instead of running the app. This should take you to the main method where the main form would be initialized.
I am using Visual Basic 2010 and I am makeing a simple login app it prompts you for a username and password if it gets it right I want to open a form then close the previus one but when I do me.close it ends the program and I can't go on
I am positive its working because I get the right password and username ut I can't close the first windows
I tried to hide it but when I do I cant close it and the program goes on without quiting and with a hidden form
I heard rumers that there is Sub that can control the x in the corner
if there is one that would probably solve my problem but I can't find it heres the code for the login form
Public Class Main_Login
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If TextBox1.Text = "My Name" And TextBox2.Text = "mypassword" Then
Contentsish.Show()
Me.Hide()
Label3.Hide()
Else
Label3.Show()
End If
End Sub
End Class
Then the Form if you enter the right login info
Public Class Contentsish
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label1.Hide()
Timer1.Stop()
End Sub
End Class
how can I fix this problem?
Go into your project settings and set the application to close when the last form closes and not when the startup form closes.
edit: I just checked some of my VB.Net 2k8 code. What I do is create a new instance of the "child" form, do any initialization that I need, call .Show() on it, and then call .Close() on the current form (Me.Close()). Probably not the best way to do things, but it works for me. This is with the project setting I described earlier set. This allows me to exit from the child form or "logout" if needed.
Two other ways you can do this, in addition to Crags:
Load the main form first, then load the password from the main form.
You can use a separate vb module and use the Sub Main for the startup (you specify this in Project Properties, Application, Startup Object), then load the two forms from Sub Main.
So what happens if the login is incorrect? Sounds like you might want to show the login form using ShowDialog, maybe in your Main() before calling Application.Run(new FormMain());
I have a mdicontainer form that summons forms. My problem is when the a user clicks again the menu for that form, it also make another instance of it.
What I did is declare a public class with a public variable on it ex: Boolean isFormOneOpen = false. Then every time formOne opens, it checks first the global variable I declared a while ago if it's false, if it is, instantiate an object of a formOne and then show it. Otherwise, do nothing. Very static, imagine if I have many forms, I have to declare a variable for each form to check if it's already open. Can you provide me a solution for this? Maybe a method that accepts a Form? Or any more clever way to do this.
You don't need a variable, you could iterate the MdiChildren collection to see if the form is already opened. For example:
Private Sub btnViewChild_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnViewChild.Click
For Each child In Me.MdiChildren
If TypeOf child Is Form2 Then
child.WindowState = FormWindowState.Normal
child.Focus()
Exit sub
End If
Next
Dim frm As New Form2
frm.MdiParent = Me
frm.Show()
End Sub
The VB.NET-centric solution:
Private Sub btnViewChild_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnViewChild.Click
Form2.MdiParent = Me
Form2.WindowState = FormWindowState.Normal
Form2.Show
End Sub
Rather than a boolean, declare a variable of the form's type. Then just make sure the variable isn't Nothing and call it's .Open() method. This has the nice side effect of also bringing your existing form instance to the front if it's already open.
Even better, in VB.Net 2.0 and later all forms have a default instance with the same name as their type, so you can just say FormName.Open() and be done with it. However, I haven't tried this in an mdi situation before.