Best practice for sharing variables across forms in VB.NET - vb.net

I need to share variables across two forms in VB.NET. One of them is the main form and the other is a child form.
I have been searching, and I have found a few methods. I want to use the best method to do this. I have listed a few options below. Please comment on which one would be the best option:
Create a static/shared variable in one of the forms and access it in the other forms via:
Form1 frm = new Form1(); // Creating object of parent to access shared variable
frm.a = "abc"; // Passing value
Send an instance of the main form to the child form when creating the child form. The variables can then be accessed via a property function.
Create global variables in a module. This seems like the easiest option, but I doubt it is the best option.
I also read something about delegates and events, but I don't know how to implement this.
If there is another method I haven't mentioned, please share it with me.

There is no one answer to the question. All the methods you listed should 'work.' Which you should use depends why you want to share the variable. For example:
Say you have a form with a list of records, and the user double-clicks a record, so you want to open a new form to edit the record, and you want to pass the record ID. In this case I would add a constructor method to the second form:
Sub New(RecordID as String)
'Add code to load the record here
End Sub
Say some of the forms in your application may want to know the database path or something else global like that. For that, I would make the appropriate variable on the parent form into a Public variable (called a Field) and access it as MainForm.FieldName. (Disclaimer: Purists will say you shouldn't rely on the somewhat messy fact that VB.NET automatically instantiates an instance of the form class and lets you refer to it by the form name, and that you should instead get a pointer to the actual instance of the form and store it in your child form and access the parent form like that. Actually, this is like number '2' in your post. But it's not actually necessary if you don't mind programmatical incorrectness.)
Say there is something global in your app, like the time the app was started, so you can tell the user "You've been using the app for 5 hours, go get a life!" These things could be stored in a module. (Or in the application class but that's quite hidden)

Create two forms. Add 3 radio buttons and 1 button to form1. Add a label to form2. In the code for form1 type
Public rdb As Integer = 1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.Show()
If RadioButton1.Checked Then
rdb = 1
ElseIf RadioButton2.Checked Then
rdb = 2
ElseIf RadioButton3.Checked Then
rdb = 3
End If
End Sub
Then in form2's code
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = Form1.rdb
End Sub

Store your global variables in a Module1.vb file, they must be publicly declared to be accessible from all forms:
Public X as String
Public Y as Integer
Then just use them as you would any other variable on any page:
X = "Hello"
Y = 10
Textbox1.Text = X
Textbox2.Text = Y
It's not the safest practice so it shouldn't be used for all your variables. But it is very neat and simple.

The child form can have public get and set functions for a private variable, and the parent form can set it when it changes and its end, or get it before it uses it to see if it has changed in the child form.

You can add public properties to either form. They can access those properties from each other. (That is not called shared though, and is not static in most cases.)

Not sure if this answers the question but one thing I found useful was to refer to the variables in form1 while programming in form2 as Form1.variablename and when in Form1 and referring to variables in Form2 to use in Form1 as Form2.variablename Basically, refer to variables in other forms by putting the name of the form they are in followed by a . and then the variable name

Related

Vending Machine Project VB: Money Not Displaying As I Would Like

I'm making a vending machine project in VB and am fairly new to VB. I'm using Visual Studio 2017. Every time I click a button, I want the money to add up in the textbox.
For example, if I click the button 10p once, and then click it again I would want the textbox to display 20p.
I have tried using += in Visual basic but it doesn't work. I've tried googling solutions but I can't seem to find any, so as always, this is my last resort.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click​
Dim total_money As Integer​
Dim clicks As Integer​
Const pence_sign As String = "p"​
​
clicks += 1​
​
txtMoneyDisplay.Text = (10 * clicks) & pence_sign​
I have no error messages which I can't fix.
But if I click 10p twice it won't show as 20p it will keep on showing as 10p, no matter how many times I click, how can I fix this?
The fix you should apply is moving this line Dim clicks As Integer to be outside of the function Sub Button1_Click making it a member variable instead of a local variable.
Example:
Public Class Form1
Dim clicks As Integer
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click​
Dim total_money As Integer​​
Const pence_sign As String = "p"​
clicks += 1​
txtMoneyDisplay.Text = (10 * clicks) & pence_sign
Simple Further explanation
Local variables will be re-created each time the function is fun. They will be assigned either the default value (in the vase of Integers, this will be 0 (Zero)) or whatever value you initialise them to.
Moving the declaration to be outside of the function turns them in to Member Variables. Member variables hold their value as long as the class containing them (and the Object referencing the class) remains in existence. In this case, the Form class will remain in existence while the form is displayed. The member variable will be reset when the class is re-created (or the Form is re-displayed)
Additional
You may want to include a button to return the customer money to them, in code for your app, this would translate to a function that will set the clicks member variable to 0. This is the same as re-initialising the member variables, resetting your applications state to the same as when it first loaded.
This is an MSDN article that may help you: Variable Declaration in Visual Basic

Passing form with reference to itself

I have the following problem:
I have 2 windows forms ("Main" and "Form2") and separated class "PI".
Using panel, I display "Form2" inside "Main".
Code from "Main":
Dim frm As new Form2 = Form2()
panel1.Controls.Add(frm)
frm.Show()
That's working fine. After clicking on the button from "Form2" the program went to class PI to do some calculations, this works fine also, but when all calculations from class PI are finished, I need to pass results back to the "Form2" using the following code (test is just string public variable). Code from "PI":
Public Shared Sub Test
Form2.test = "It works!"
end sub
Code from "Form2":
Public test As String
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
PI.Test()
MsgBox(test)
End Sub
So, the problem is that without panel, if I open Form2 independently (not inside "Main", passing variables in this way works good (msgbox shows the statement), otherwise - it doesn't (empy box). Could you please tell me what is wrong and how can I fix it.
Thanks in advance!
Why it works on standalone Form2:
In
Public Shared Sub Test()
Form2.test = "It works!"
End Sub
you are always addressing default instance of Form2. It is that one you simply call as standalone in case you are describing as "works as expected".
But in your code
Dim frm As new Form2 = Form2()
panel1.Controls.Add(frm)
frm.Show()
you are creating new (another) instance of your Form2.
Use the original default instance there (if you need only one Form2), i.e. do not use new, and it will start working.
panel1.Controls.Add(Form2)
Structuring your code like this couples PI and Form2 together - they know too much about each other. Generally we prefer classes like PI to be independent from the UI code that uses them - it makes them easier to work with, reuse and debug.
I don't know what the result of the Test method is (in your example it's just a string), but you should make it so that the Test method returns it, then Form2 can use it.
If the result is more complicated (maybe it's several values) you could create a class to contain the result values and return an instance of that class from Test. Or you could just set multiple attributes on the PI instance and change the Form2 code to get the values from those attributes after calling Test. (This isn't as nice as returning the value, but it might be simpler, and it's much better than having PI set results on Form2 directly.)

Declare a "type" object globally

I want to pass objects between form modules.
I have made a simple database to explain the problem I am having.
I have two forms --> form1, form2 and one module --> Module1
Based on the threads I have read, I believe if I want to define a global object, it should be done in the module so I placed the declaration there;
Option Compare Database
Public Type Name
First As String
Last As String
Phone As String
End Type
On form1 I have a cmd button with the following code behind it;
Option Compare Database
Dim My_Name As Name
Private Sub cmd_Button_Click()
My_Name.First = "MyFirstName"
My_Name.Last = "MyLastName"
MsgBox ("In Form1 " & My_Name.Last)
DoCmd.OpenForm "Form2"
End Sub
on the second form I have;
Option Compare Database
Dim my_Name As Name
Private Sub Form_Load()
MsgBox (my_Name.First)
End Sub
In the first form, I see the my_Name object variable fine, when I pass control to the second form, I lose the variable.
I have tried a number of variations of Public, Static declarations all over the place on both the object variable and the sub's but I cannot figure out how to preserve the object across modules.
You are re-declaring my_name. So it is in -effect two different things. Like george forman and george forman.
I am sorry I can't be more help it's been like a a million years since I have had to deal with this. However, it seems that your 'froms' are actually declared in an 'module' like block -name from1. That from global scope you can reference a variable in your form1.
In this case form1.my_name. However, this can lead to issues if form1.my_name has not yet been instanciated.
My recommendation is to find the module with global scope ( I dont remember exactly what it is, if you have to create it or now, and when it gets life). Declare and initicialize your variables in it. Then access those from within you event handlers ("cmd_Button_Click" for example.)

Passing References through forms vb.net

Is there anyone with very good knowledge in vb.net. I am working on my final semester project. I need to pass objects between forms. I have my codes of two forms here.
http://pastebin.com/xP1LdL3t
http://pastebin.com/fpuY98NT
To connect to the irc server i am using irc.Connect() function. It is perfectly working on my channel form and it is to be called only when users want to connect or on form load. When i double click the online user list a private message form opens. And i am unable to send irc.sendraw command and that form has not called irc.Connect(). It is not supposed to be called in every form. What i want is to use the channel's connection status on other forms so that irc.sendraw command will work.
If i have failed to explain properly please let me know.
It's not clear what you mean by "pass references". There are several ways to communicate between forms. Here are a few:
Declare public variables or properties in one form to be accessed by other forms. If you do this, be sure you are using the proper instance of the form containing the public variables. If you refer to one of these variables before that form is loaded, you'll end up with two instances of the form and things will get confusing.
Use a public method, similar to (1)
Declare global variables in a separate module, to be accessed by any form in the project. (Some people consider this bad manners.)
Pass parameters to and from the forms.
Raise an event to be handled in another form.
basically,
If you want to pass through function in Form 1 to function in Form 2 you can do somthing like this:
Public Class Form1
Dim x As Integer = 2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.fun(x)
Form2.Show() ' it's optional
End Sub
End Class
and in Form 2 you just get the value as ref:
Public Class Form2
Dim y As Integer 'the variable to get the value of x
Public Sub fun(ByRef x As Integer)
y = x
End Sub
End Class
Hope it can help you, and it's what you wanted.

Catch a value from form1 to form2 in vb [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
In VB, I create 2 forms in 1 project. In form1, I put 3 buttons with different value. In form2, I only put 1 textbox with no value.
My question is, how if I press one of the button in form1, the form2 is automatically opened and the value from the button that I press automatically added to the form2 textbox?
Add following code into your button handler. You can double click button and add the code into event handler which is automatically created:
'Here we are creating actual object and passing string into it constructor method
Dim instanceOfForm2 = new Form2("String value from Form1!")
instanceOfForm2.Show() ' Showing form
In Form2 we need to tweak our constructor to accept one parameter:
Public Sub New(someValue as String)
InitializeComponents() 'This is always first row in form constructor
TextBox1.Text = someValue 'And put that text into textbox...
End Sub
In VB6 you can do all the stuff that lardymonkey has in place, but you don't have to. The most concise way to do what you want is this. First, make your three command buttons in Form1 into a control array. To do this, give them all the same name (I'll use "cmdMyButtons" in my example), and set their index properties to 0, 1, and 2. Then do this in Form1's code window:
Option Explicit
Dim ButtonText(2) As String
Public Sub Form_Load()
ButtonText(0) = "First Button Text"
ButtonText(1) = "Second Button Text"
ButtonText(2) = "Third Button Text"
End Sub
Public Sub cmdMyButtons_Click(Index As Integer)
With Form2
.txtMyTextBox.Text = ButtonText(Index)
.Show vbModal
End With
End Sub
Now, I like lardymonkey's idea of showing modally, so I put it in here as well. However, several things in his code sample aren't intrinsically necessary to do what you want, and create overhead, so I pulled them out:
You don't need to make a property; you can just set the text
directly as I have here.
You don't need to create a form variable; you can just reference the form directly as I have here.
You don't have to load the form explicitly; the form gets
automatically loaded as soon as you set the variable (by the way,
the Show method also automatically loads the form, too--you only use
Load when you want to have the form loaded into memory before you do
anything to it).
If you close the modal form it will be
automatically unloaded. However, unloading a form doesn't set any
object variables referencing it to nothing. Therefore, frmDetail
will not be Nothing when you check it, you will unload a form that
isn't loaded. While this doesn't throw an error (the statement is ignored), I wouldn't do it anyway. So, you don't
need any of the "make sure the form is destroyed" code.
And now, for a short lecture on the whole business of always explicitly destroying object variables:
There is a longstanding argument about whether you need to explicitly set all your local object variables to Nothing before exiting a subroutine in VB6. I don't agree with this at all; VB takes care of this automatically when the variables go out of scope. As far as I can see, the reason that people believe that they have to do this is that the scope finalizer doesn't collect garbage in any particular order, and sometimes two interacting COM objects need to be destroyed in a particular order due to poor coupling architecture. In such a case, you do indeed need to clear the objects in the correct order to work around intermittent bugs, so the myth developed that VB's garbage collection is buggy and needs to be circumvented by always manually destroying object variables.
Frankly, the idea that a programmer is going to always do this and never forget is naive. So I persist in disagreeing with it; the developers of VB6 put a lot more thought and effort into developing the scope finalizer than any programmer is going to put into circumventing it.
Without knowing the specific version of the software you are using we cant answer, we can answer it if you provide the correct version
In .net it's a simple as creating the form then passing the value over.
Friend objForm2 as New Form2
Private Sub button1_Click(ByVal sender As System.Object, ByVal e as System.EventArgs) Handles button1.Click
objForm2 = new Form2()
TextBox1.Text = value
End Sub
This would be a way of doing it in VB6. I've left the error handling up to you.
I've made the assumption that the name of the text box is txtOutput on form2.
In Form2 add the following:
Option Explicit
Public Property Let OutputText(ByVal strOut As String)
txtOutput.Text = strOut
End Property
In Form1 add the following:
Option Explicit
Private Sub Command1_Click()
DisplayForm "1"
End Sub
Private Sub Command2_Click()
DisplayForm "2"
End Sub
Private Sub Command3_Click()
DisplayForm "3"
End Sub
Private Sub DisplayForm(ByVal strValue As String)
'Declare the variables
Dim frmDetail As Form2
'Create the form
Set frmDetail = New Form2
'Load the form and display it modal
Load frmDetail
frmDetail.OutputText = strValue
frmDetail.Show vbModal, Me
'Make sure the form is destoryed
If Not frmDetail Is Nothing Then
Unload frmDetail
Set frmDetail = Nothing
End If
End Sub
Make sure you comment the code and if you need some error handling then add it. If you need help with the VB6 functions you can find it here MSDN VB6 Reference