Passing Variables between Instances of a class

Jerim

Member
Joined
Jun 17, 2009
Messages
6
Programming Experience
1-3
I created a program a while back, in the traditional VB.NET way by drawing a bunch of forms. I have started playing around with creating the forms at runtime using classes. I have a placeholder form called frmStartup which merely calls the CreateLogin() sub from the CreateFormClass. The CreateLogin() sub creates a new blank form, then calls the grpbxLogin(), btnSave() and btnExit() subs from the FormElementClass which adds all the buttons and textboxes to the form. Within the FormElementClass, I have associated btnSave and btnExit with event handlers. These even handlers call subs from the DataProcessingClass. The event handler for Exit works just fine.

I am having a problem with the Save event handler. Precisely, I don't know how to pass either the username or password from the Login form to the btnLogin_Click() sub in the DataProcessingForm. I have tried using Me. and frmLogin., but the program doesn't see either of those. If the Login form is an instance that is disposed of once another Sub is called, then it won't exist later on to call from. I have tried declaring variables and passing those along to btnLogin_Click, but no matter where I put it, the program doesn't see txtbxUsername.Text or txtbxPassword.Text. Not even from within FormElementsClass, which is were the boxes are created.

Any ideas on how to pass variables in this case? I am not even sure what you would call this such as passing between classes, or passing between instances.

--------------------------------------------------------------------------
frmSTARTUP.VB
Imports System
Imports System.Data
Imports System.Windows
Imports Login.CreateForm

Public Class frmStartup
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Using CreateFormObject As New CreateFormClass
CreateFormObject.CreateLogin()
End Using
End Sub
End Class
--------------------------------------------------------------------------
CREATEFORMCLASS.VB
Imports System
Imports System.Data
Imports MySql.Data.MySqlClient
Imports MySql.Data
Imports System.Windows
Imports Login.FormElements
Imports Login.DataProcessing

Namespace CreateForm
Public Class CreateFormClass
Inherits ObjectDisposeClass

Public Sub CreateLogin()
Dim frmLogin As New Form
frmLogin.Text = "Login"
frmLogin.MaximizeBox = False
frmLogin.MinimizeBox = False
frmLogin.ControlBox = False
frmLogin.Height = 160
frmLogin.Width = 325

Using FormElementsObject As New FormElementsClass
FormElementsObject.grpbxLogin(frmLogin, 5, 10)
FormElementsObject.btnLogin(frmLogin, 150, 90)
FormElementsObject.btnExit(frmLogin, 230, 90)
End Using

frmLogin.Show()
End Sub

#Region " IDisposable Object ..."
Edited out the code
#End Region
End Namespace
-------------------------------------------------------------------------
FORMELEMENTSCLASS.VB
Imports System
Imports System.Data
Imports MySql.Data.MySqlClient
Imports MySql.Data
Imports System.Windows
Imports Login.CreateForm
Imports Login.DataProcessing

Namespace FormElements
Public Class FormElementsClass
Inherits ObjectDisposeClass

Public Sub grpbxLogin(ByVal frmName, ByVal x, ByVal y)
Dim grpbxLogin As New GroupBox
grpbxLogin.Location = New Point(x, y)
grpbxLogin.Width = 300
grpbxLogin.Height = 70
grpbxLogin.Visible = True
frmName.Controls.Add(grpbxLogin)

Dim lblUsername As New Label
lblUsername.Text = "USERNAME:"
lblUsername.TextAlign = ContentAlignment.MiddleRight
lblUsername.Visible = True
lblUsername.Height = 20
lblUsername.Width = 100
lblUsername.Location = New Point(5, 15)
grpbxLogin.Controls.Add(lblUsername)

Dim lblPassword As New Label
lblPassword.Text = "PASSWORD:"
lblPassword.TextAlign = ContentAlignment.MiddleRight
lblPassword.Visible = True
lblPassword.Height = 20
lblPassword.Width = 100
lblPassword.Location = New Point(5, 40)
grpbxLogin.Controls.Add(lblPassword)

Dim txtbxUsername As New TextBox
txtbxUsername.Text = ""
txtbxUsername.Visible = True
txtbxUsername.Height = 20
txtbxUsername.Width = 150
txtbxUsername.Location = New Point(105, 15)
grpbxLogin.Controls.Add(txtbxUsername)

Dim txtbxPassword As New TextBox
txtbxPassword.Text = ""
txtbxPassword.Visible = True
txtbxPassword.Height = 20
txtbxPassword.Width = 150
txtbxPassword.Location = New Point(105, 40)
grpbxLogin.Controls.Add(txtbxPassword)
End Sub

Public Sub btnLogin(ByVal frmName, ByVal x, ByVal y)
Dim btnLogin As New Button
btnLogin.Visible = True
btnLogin.Text = "LOGIN"
btnLogin.Location = New Point(x, y)
Using DataProcessingObject As New DataProcessingClass
AddHandler btnLogin.Click, AddressOf DataProcessingObject.btnLogin_Click(Username, Password)
End Using
frmName.Controls.Add(btnLogin)
End Sub

Public Sub btnExit(ByVal frmName, ByVal x, ByVal y)
Dim btnExit As New Button
btnExit.Visible = True
btnExit.Text = "EXIT"
btnExit.Location = New Point(x, y)
Using DataProcessingObject As New DataProcessingClass
AddHandler btnExit.Click, AddressOf DataProcessingObject.btnExit_Click
End Using
frmName.Controls.Add(btnExit)
End Sub

#Region " IDisposable Object ..."
Edited out code
#End Region
End Namespace
-------------------------------------------------------------------------
DATAPROCESSINGCLASS.VB
Imports System
Imports System.Data
Imports MySql.Data.MySqlClient
Imports MySql.Data
Imports System.Windows
Imports Login.CreateForm
Imports Login.FormElements

Namespace DataProcessing
Public Class DataProcessingClass
Inherits ObjectDisposeClass

Public Sub btnLogin_Click(ByVal Username, ByVal Password)
Bunch of MySQL code for verifying username and password
End Sub

Public Sub btnExit_Click()
Environment.Exit(0)
End Sub
End Class

#Region " IDisposable Object ..."
Edited code out
#End Region
End Namespace
--------------------------------------------------------------------------
 
After some research, it seems that there is a way to pass variables to the event handler. What I have right now is

Public Sub grpbxLogin(ByVal frmName, ByVal x, ByVal y)
Dim txtbxUsername As New TextBox
txtbxUsername.Text = ""
txtbxUsername.Visible = True
txtbxUsername.Height = 20
txtbxUsername.Width = 150
txtbxUsername.Location = New Point(105, 15)
AddHandler txtbxUsername.Leave, AddressOf txtbxUsername_Leave
grpbxLogin.Controls.Add(txtbxUsername)
End Sub

Private Sub txtbxUsername_Leave(ByVal Username)
MsgBox(Username)
End Sub

What I have found only mentions overloading the event handler to accept variables. Is that really the only way to do it? I was expecting to be able to do something such as:

AddHandler txtbxUsername.Leave(Dim Username as String = txtbxUsername.Text)

That just seems so much more logical.
 
In your button event handler you could use
VB.NET:
        Dim UName As String = DirectCast(DirectCast(sender, Button).FindForm(), frmLogin).txtbxUsername.Text.Trim
        Dim PWord As String = DirectCast(DirectCast(sender, Button).FindForm(), frmLogin).txtbxPassword.Text.Trim
 
I appreciate the help. I tried that, with the same result. The error that I am getting is "Error 'txtbxUsername' is not a member of 'New_Quality_Audit.frmForm'." This makes sense, since I am seperating things out into different classes. Just a quick rundown of what I have:

frmForm.vb:
Public Class frmForm
Public Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Using CreateFormObject As New CreateFormClass
CreateFormObject.CreateLogin()
End Using
End Sub
End Class
---------------------------------------------------------------
CreateFormClass.vb:
Public Sub CreateLogin()
Dim frmForm As New Form
With frmForm
.Name = "frmForm"
.Text = "Quality Audit - Login"
.MaximizeBox = False
.MinimizeBox = False
.ControlBox = False
.Height = 160
.Width = 325
End With

Using grpbxLoginObject As New GroupboxClass
grpbxLoginObject.grpbxLogin(5, 10)
End Using

Using ButtonClassObject As New ButtonClass
ButtonClassObject.btnLogin(150, 90)
ButtonClassObject.btnExit(230, 90)
End Using
ClearLogin()
End Sub
-------------------------------------------------------------------
TextboxClass.vb:
Public Sub txtbxUsername(ByVal x, ByVal y)
Dim txtbxUsername As New TextBox
txtbxUsername.Text = ""
txtbxUsername.Visible = True
txtbxUsername.Height = 20
txtbxUsername.Width = 150
txtbxUsername.Location = New Point(105, 15)
frmForm.Controls.Add(txtbxUsername)
End Sub
-------------------------------------------------------------------------
ButtonClass.vb:
Public Sub btnLogin(ByVal x, ByVal y)
Dim btnLogin As New Button
btnLogin.Visible = True
btnLogin.Text = ""
btnLogin.Location = New System.Drawing.Point(x, y)
btnLogin.Size = New System.Drawing.Size(368, 20)
btnLogin.Location = New Point(x, y)
Using ButtonActionObject As New ButtonActionClass
AddHandler btnLogin.Click, AddressOf ButtonActionObject.btnLogin_Click
End Using
frmForm.Controls.Add(btnLogin)
End Sub
----------------------------------------------------------------------
ButtonActionClass.vb:
Public Sub btnLogin_Click()
Dim Username As String = frmForm.txtbxUsername.text

The error comes in the btnLogin_Click() method. Since txtbxUsername won't be added to the form until runtime, VB doesn't see that txtbxUsername is a member of frmForm. And since there is an error, it won't compile. Is there some way I can associate the two? I am using various files and classes as a learning tool.

I realize I could consolidate some things into the same forms, but I am trying to learn how to do it this way. I am trying to make the program as "organic" as possible, instead of having to hardcode each form. Any help is greatly appreciated.

BTW, as far as I can tell, I am calling all the class files correctly. If I take out that variable declaration in btnLogin_Click() the program compiles and runs. The login form looks like it should, with frmForm calling the textboxes and buttons. It is just that when I click on Login, it doesn't do anything.
 
Last edited:
Ok give this a try

VB.NET:
        Dim UName As String = DirectCast(DirectCast(DirectCast(sender, Button).FindForm(), frmLogin).Controls.Find("txtbxUserName", True)(0), TextBox).Text
        Dim PWord As String = DirectCast(DirectCast(DirectCast(sender, Button).FindForm(), frmLogin).Controls.Find("txtbxPassword", True)(0), TextBox).Text

The innermost DirectCast gets us the Button control, which we use to find the form, cast that as the frmlogin so we can access the control collection and then we can search the controls for one by name. Since the Controls.Find returns an array of controls and we are searching for a specific name that we know is in the collection it should be the first one in the array (0). We cast this object as a textbox since that is what we are looking for.

I didn't have time to put together an extensive list of classes that you have but in theory this should get the information you want from the textboxes, since there are no explicit refernces.

You may want to look into the Reflection Namespace also.
Reflection
 
Your button click event should be have the normal click event signature:

Public Sub ButtonClick(ByVal sender As System.Object, ByVal e As System.EventArgs)

I think that might help, not sure though.

I tried creating a project from the code that you have printed but there were too many unknowns to quickly do it. Is it possible you post the project?
 
The solution/project is attached. frmForm.vb is the startup form, so you can start there and should be able to follow the code. Let me know if you have any questions.
 

Attachments

  • New Quality Audit.zip
    26 KB · Views: 6
Last edited by a moderator:
Give your controls a Name
VB.NET:
txtbxUsername.Name = "txtbxUsername"
then you can find them again by that string.
VB.NET:
Dim username As String = DirectCast(sender, Button).FindForm().Controls.Find("txtbxUserName", True)(0).Text
 
Back
Top