How do I use textbox controls in VB class? - vb.net

I am trying to create an EmployeeID in an 'employee' class using a method. But the ID needs to be able to extract a letter from the 'firstname' textbox in the main design form and then use that to create a unique ID. But I'm unable to call/use any form controls in any of the classes, as they only work on main form. How do I pass the controls to the class so I can do this inside the 'employee' class method instead of the main form?
I hope this makes sense.

I agree that this is the wrong way to approach this. However, it is possible to access a form's controls from a class. You can do this either by accessing open forms (assuming it's open) or passing the textbox as an argument.
Form:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim EmployeeA As New ClassEmployee
Dim EmployeeAID = EmployeeA.GetEmployeeIDFromOpenForm()
MsgBox("Open Form: " & EmployeeAID)
MsgBox("Passing Control: " & EmployeeA.GetEmployeeIDFromControl(TxtFirstName))
End Sub
Class:
Public Class ClassEmployee
Public Function GetEmployeeIDFromOpenForm()
Dim FirstNameText = Application.OpenForms.Item("Form1").Controls.Find("TxtFirstName", True).SingleOrDefault().Text
Return FirstNameText
End Function
Public Function GetEmployeeIDFromControl(FirstNameTextBox As TextBox)
Return FirstNameTextBox.Text
End Function
End Class

Related

How to access data from calling object in vb.net

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

Open Form By Variable Value

Form Name comes from a variable. I would like to open Form from variable value.
In VBA load("UserFormName") will show the form. But I don't know how to do it in VB.Net.
Ok, of course one would want to be able to open a form by string name.
When you create a vb.net winforms project, then all forms are available as a "base" static class.
You often see a LOT of code thus simply use the base form class.
If I need to display say form2, then I really don't need to create a instance of that form (unless you want to have multiple instances of that form. So a truckload of code will simply launch + use the "base static" class of that form.
eg:
Form2.Show()
I don't consider this all that bad of a practice, since what do you think the project settings to "set" the startup form in the project settings does?
It simply sets the built in instance of "mainForm" = to your startup form and it does NOT create new instance.
So, now that we all can agree for 15+ years anyone who has set the startup form in their project is NOT creating a NEW instance of that form, but in fact using the base class instance. This is really a programming choice.
So, code to display (show) the base static instance of a form by string name will look like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strForm As String = "Form1"
ShowFormByName(strForm)
End Sub
Public Sub ShowFormByName(strFormName As String)
System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(ProductName & "." & strFormName).show()
End Sub
Private Function FormByName(strFormName As String) As Form
Return System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(ProductName & "." & strFormName)
End Function
However, above includes a helper sub that will simply "show" that built in instance of the forms.
And above also includes a function to return class type of the form, since for sure a good many developers prefer to first create a instance of the form, and then "show()" it.
So, often we do want multiple instances, or we just perfer the codeing approach of creating a new instance of the form object.
So, we use the 2nd helper function to return a form object of the type we passed by string.
So, to display 3 instances of form1, but the FIRST instance being the base class, then two more but brand new instances of that form, we have this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strForm As String = "Form1"
ShowFormByName(strForm)
Dim f1 As Form = FormByName(strForm)
Dim f2 As Form = FormByName(strForm)
f1.Show()
f2.Show()
End Sub
So the above code snip shows how to display the built in base class form without having to create a instance of that form.
However, the next two forms we load are "new" instances of that form as "string".
So the helper sub, and helper function will give you both choices as to which preference floats your boat.
Dim form = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(Application.ProductName & "." & MySubForm)
Dim frm As New Form
frm = form
frm.MdiParent = AFrmMainScreen
frm.WindowState = FormWindowState.Maximized
frm.Show()
I prefer to use Reflection.Assembly.GetEntryAssembly because I use several different projects in one solution. This allows me to put this code in a different project(dll) that has a usercontrol that I can then reuse across multiple solutions. You also don't need to know the "Namespace" for the form as long as it is in the startup project.
The code below gets the form type from the exported types from the entry assembly and then uses Activator.CreateInstance to create a new instance of the form. Then I return that form in the function.
Public Function GetForm(ByVal objectName As String) As Form
Try
Dim frmType = Reflection.Assembly.GetEntryAssembly.GetExportedTypes.FirstOrDefault(Function(x) x.Name = objectName)
Dim returnForm = TryCast(Activator.CreateInstance(frmType), Form)
Return TryCast(returnForm, Form)
Catch ex As Exception
Return Nothing
End Try
End Function
To use the above function:
Dim MyForm = GetForm(FormLocation)
If MyForm IsNot Nothing Then
MyForm.ShowDialog()
'You can do any form manipulation from here.
Else
MessageBox.Show($"{FormLocation} was not found.")
End If

How do I pass an object to a default form instance

I understand its possible to open the "default instance" of a form in vb.net by calling NameOfTheForm.show()
How do I pass an object to the default form instance so i can work on the object and use it to populate the forms Text boxes?
I've tried to add a parameter to the frmNames New method but I'm not sure how then to open the form. The old style instantiate an object works:
Dim DetailsForm As New frmOrder(oOrder)
DetailsForm.Show()
But I'm used to using the :
frmOrder.show
syntax.
Should I use the top method or should I use the bottom method and have a public property on the form to accept the Object?
Have a missed a better method of doing this?
Thanks
Your calling method should use your first option
'Careful about declaring this in a sub, because when that sub ends, the form might get closed.
'It might be best to declare this as an instance var (aka form-level var)
Private DetailsForm As frmOrder
'this could go in an event handler, or anywhere
DetailsForm = New frmOrder(oOrder)
DetailsForm.Show()
You will need to add a constructor to your DetailsForm:
Private _oOrder as OrderType
Public Sub New(oOrder As OrderType)
'Best to save it to a private instance var and process it during Form_Load
_oOrder = oOrder
End Sub
Then when your Form_Load() runs, it can use your private instance var to fill your TextBoxes, like you want.
A second, but less eloquent approach would be to add a public property to the form and after you call .Show(), you can assign a value DetailsForm.OrderObject = oOrder, and then process the object that was passed-in.
The constructor approach is better because it can be "compiler checked"
If you really feel you must use default instance.
In Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form2.myObject = New Coffee("Breakfast Blend", 7)
Form2.Show()
End Sub
In Form2
Public myObject As Coffee
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TextBox1.Text = myObject.Name
TextBox2.Text = myObject.ID.ToString
End Sub

Get form control using string name VB.NET

I have a control on a form UserNameCtrl and that control has a sub called LoadCtrl
I essentially have loads of these subs for clicks, so I want to put them all into one event handler
Private Sub NewsletterBtn_Click(sender As Object, e As EventArgs) Handles NewsletterBtn.Click, NewsletterImage.Click
If Not MainNewsletterCtrl.Loaded() Then MainNewsletterCtrl.Load()
End Sub
However within each of the subs the control names are hardcoded to call the .loaded and .load functionality.
I've wrote a new version of this
Private Sub GenericNavItem_Click(sender As Object, e As EventArgs)
Dim ctrl As Control = Controls.Find(sender.tag, True).FirstOrDefault
'Want to do the Controlname.Load here
End Sub
Using the tag (which I named as the control name) I got the corresponding control. But it's bringing back it as a control rather than of the type I want it to be.
I know I declare it as Control, but I don't know how I can cast it to be the ControlName.Load rather than the generic control.
If they are all the same class (or base class), then just cast to that class. If they are all different class but have the same method Load and Loaded, then I suggest you create an interface.
Interface ISomeName
Sub Load()
Function Loaded() As Boolean()
End Interface
Make sure all your class implement it and then just cast to that interface.
Private Sub GenericNavItem_Click(sender As Object, e As EventArgs)
Dim ctrl As Control = Controls.Find(sender.tag, True).FirstOrDefault
Dim ctrlInterface As ISomeName = CType(ctrl, ISomeName)
If Not ctrlInterface.Loaded() Then ctrlInterface.Load()
End Sub

How to store a variable after form closes for use later on another form

So I am building a form based application, and I am running into an issue with passing data between forms. I have a combo box that, based on selection, triggers a new form to open with several buttons to pick from. Once you select a button, the form closes, but I can't get the selection to be carried over to the original form.
basic idea of the code is like this
Public Class frmMain
Public intStore As integer
Private Sub cboSample_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboSample.SelectedIndexChanged
Dim selection as Integer
selection = cboSample.SelectedIndex
If selection = -1 Then
Else
Select Case selection
Case 0
frmOne.Show()
Case 1
frmTwo.Show()
End Select
End If
End Sub
End Class
Here is a sample of the second form code
Public Class frmOne
Public storage As varStorage
Private Sub btn_Clicked(sender As Object, e As EventArgs) Handles btn.Clicked
storage = New varStorage With {.datastore = 1}
Me.Close()
End Sub
End Class
frmTwo is pretty much the same but handles more options
The Class I created looks like this
Public Class varStorage
Public _dataStore As Integer
Public Property dataStore() As Integer
Get
Return _dataStore
End Get
Set (value As Integer)
_dataStore = value
End Set
End Property
End Class
as I said, the issue comes from the point of the form being called, and the form closing, the variable data is not being saved. I am almost certain I am missing some code somewhere, but not sure where. any help would be greatly appreciated.
Rather than using Show() to open another form, using ShowDialog() will open the form modally. The form will behave like a MessageBox. It will wait for you to respond to, and close, this form before returning to your main form. We can obtain a value from this modal-form, safe in the knowledge that the form has been closed (and so the value we have obtained will not be changed).
The other way is to make a Public Property of the form. then you can create Get and Set methods to have access to your form objects
Public Class yourFormClass
Public Property Note As String
Get
Return txtNote.Text
End Get
Set(value As String)
End Set
End Property
End Class
and Then you can use it like
dialog = New yourFormClass()
someOtherTextbox.Text = dialog.Note