How to call upon dynamically created objects - vb.net

Okay so here is what I have:
Do
x = x + 1
Dim myTxt As New TextBox
myTxt.Name = ("TbMat" & x.ToString())
myTxt.Location = New Point(13, 13 + (x * 37))
myTxt.Tag = "For DB"
myTxt.Visible = True
Button2.Location = New Point(13, 39 + (x * 37))
If x = 5 Then
Button1.Dispose()
End If
Me.Controls.Add(myTxt)
Me.Refresh()
Loop Until x >= 1
It's my makeshift way of letting the user add a textbox by clicking a button. I am new to programming so this may be an easy fix but here is my question... when the user adds a textbox I want the first one to be "TbMat1" so I would assume to call upon it to get information I would just use, for example, textbox1.text=TbMat1.text. When I do this, it says TbMat1 is not declared, which is obvious since it isn't created yet.
I need help pulling information from the new textboxes to other textboxes, and later I will figure out exporting. Thanks.

When you created the control, you created it as myTxt which is its object reference. So in the procedure where that code block exists this would work:
SomeOtherTB.Text = myTxt.Text
The name is just the name, not an object reference or 'handle'. Further, once the code exits that procedure myTxt goes out of scope because that is where it was declared (Dim or Private|Friend|Public). To access your new control elsewhere:
SomeOtherTB.Text = Me.Controls("TbMat1") ' or "TbMat" & x.ToString()
OR create a new object ref if you want:
Friend myTB AS TextBox ' module level at least
myTb = Me.Controls("TbMat1")
The latter might not be practical if you are making lots of them.

Related

Iterate through variables using a variable?

I'm trying to find a way to iterate through a list of Strings to be displayed in a text box. These Strings are retrieved from a separate class called 'texts'.
The Strings are declared in the 'texts' class as (for ngs1, 2, 3, etc)
Public Shared ngs1 As String = "Text"
This chunk runs when a next button is clicked, the button's purpose being to iterate through the list of texts displayed.
ElseIf firstTimeRun = True Then
welcome += 1
Select Case welcomePages
Case 1
txtDisplay.Text = texts.ngs1
Case 2
txtDisplay.Text = texts.ngs2
Case 3
txtDisplay.Text = texts.ngs3
End Select
I'm wanting to be able to do this without a select case, so that it's essentially
'Pseudo code
ElseIf firstTimeRun = True Then
welcome += 1
txtDisplay.text = texts.ngs(welcome)
I'm not sure how to properly do this, by using a variable in the name of other variables. Any help would be greatly appreciated, thanks!
If you just want to iterate through all this texts, just create a list(of String) or array and add all the ngsX...
As Example:
Dim list as List(Of String)
Dim indexActualShownString as Integer
Then you can just use in your Clicked_Event
txtDisplay.text=list.Items(indexActualShownString) as Integer
indexActualShwonString += 1
But I am not sure if I understand your problem right. And you should also implement a way to reset indexActualShownString, since I dont know what exactly its the purpose of it.

How to use reflection for accessing object from its name as a string

Ive a folder monitoring application where around 25 filewatchers monitoring 25 folders. Each of the filewatchers named fsw1,fsw2 ....
bCreateFileCheck = True
fsw1 = New FileSystemWatcher(My.Settings.UserRootFolder1)
fsw1.IncludeSubdirectories = True
fsw1.EnableRaisingEvents = True
fsw1.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName)
So this is repeating for the 25 folders, but only difference is name changing of fsw1 to fsw2,fsw3 etc. and also My.Settings.UserRootFolder1 to My.Settings.UserRootFolder2,My.Settings.UserRootFolder3 etc.
So how can we achieve this using for loop without writing individual code blocks for every filewatchers. I guess using some reflection techniques it can be achieved.
Don't make your life harder than it needed to be. Use an array (or List(Of T) if you need something flexible):
Dim watchers(24) As FileSystemWatcher
For i As Integer = 0 To watchers.GetUpperBound(0)
Dim path = CStr(My.Settings.Item("UserRootFolder" & (i + 1)))
watchers(i) = New FileSystemWatcher(path)
'Do further initialization...
Next
If the structure is fixed and you cannot really change it, you can set the variables to the objects that you created in the For loop. So change the loop as follows:
'...
Dim watcher = New FileSystemWatcher(...)
Me.GetType().GetField("fsw" & (i + 1)).SetValue(Me, watcher)
This gets the field with the appropriate name and sets its value to the object that you just created (I assume that it is a field based on its naming).

Tracking Controls via an Array

so I have an array that holds picture boxes. Can someone help me in coding a much, much more efficient way in assigning each index? I just can't figure it out.
ArrayBullets(0) = picBullet0
ArrayBullets(1) = picBullet1
ArrayBullets(2) = picBullet2
ArrayBullets(3) = picBullet3
ArrayBullets(4) = picBullet4
ArrayBullets(5) = picBullet5
ArrayBullets(6) = picBullet6
ArrayBullets(7) = picBullet7
ArrayBullets(8) = picBullet8
ArrayBullets(9) = picBullet9
ArrayBullets(10) = picBullet10
ArrayBullets(11) = picBullet11
ArrayBullets(12) = picBullet12
ArrayBullets(13) = picBullet13
ArrayBullets(14) = picBullet14
ArrayBullets(15) = picBullet15
ArrayBullets(16) = picBullet16
ArrayBullets(17) = picBullet17
ArrayBullets(18) = picBullet18
ArrayBullets(19) = picBullet19
ArrayBullets(20) = picBullet20
ArrayBullets(21) = picBullet21
ArrayBullets(22) = picBullet22
ArrayBullets(23) = picBullet23
ArrayBullets(24) = picBullet24
ArrayBullets(25) = picBullet25
ArrayBullets(26) = picBullet26
ArrayBullets(27) = picBullet27
ArrayBullets(28) = picBullet28
ArrayBullets(29) = picBullet29
It would be much appreciated.
There is generally no reason at all to do this. They can always be found in the Controls Collection (you will not find them among Components). Though it looks ordered, your list is actually a bit arbitrary; they will always be in the Controls Collection in ZOrder which starts as the order added to the Designer and may or may not matter.
If you need a way to track them, rather than storing a reference, you can use a List(Of String) to store their names to use to reference them in the controls collection. If a control reference is somehow important, then a List(Of PictureBox) could be used instead.
Private myPicBoxes As New List(of String)
Method One - add names in Form Load:
For n As Integer = 0 To 29
myPicBoxes.Add(String.Format("picBullet{0}", n.ToString))
Next n
Method Two - get names from controls in Form Load
For Each pb As PictureBox In Me.Controls.OfType(Of PictureBox)
mypicBoxes.Add(pb.Name)
Next
To do something with a particular PB:
Me.Controls( myPicBoxes( mypicBoxes(theIndex) ) ).Image = FileName
Clear all images:
For Each pbName As String in myPicBoxes
Me.Controls(pbName).Image = Nothing
Next
' or
For n As Integer = 0 To myPicBoxes.Count - 1
Me.Controls(myPicBoxes(n)).Image = Nothing
Next n
If they are dynamic (you remove or add PictureBoxes at runtime) add/remove to your List as well:
Dim pb As New PictureBox
... set props
pb.Name = whatever you want
myPicBoxes.Add(pb.Name)
Me.Controls.Add(pb)
Removing:
Me.Controls.Remove( mypicBoxes(n))
mypicBoxes.RemoveAt(n) ' also remove the name from your tracker
If you're using the form designer designer to create your UI, populating the array manually really is the simplest and probably the best option.
You could iterate over Controls to find all the PictureBoxes and put them into an array; but that won't have a guaranteed sort order because the designer loves to rearrange its code every times you change something.

Access a form's control by name

not sure whether the title of this post is accurate.
I'm trying to access windows form controls and their properties by "composing" their name within a loop, but I can't seem to find the related documentation. Using VB.net. Basically, say I have the following:
Dim myDt As New DataTable
Dim row As DataRow = myDt.NewRow()
row.Item("col01") = Me.label01.Text
row.Item("col02") = Me.label02.Text
'...
row.Item("colN") = Me.labelN.Text
I'd like to write a for loop instead of N separate instructions.
While it's simple enough to express the left-hand side of the assignments, I'm stumped when it comes to the right-hand side:
For i As Integer = 1 to N
row.Item(String.format("col{0:00}", i)) = ???
' ??? <- write "label" & i (zero-padded, like col) and use that string to access Me's control that has such name
Next
As an extra, I'd like to be able to pass the final ".Text" property as a string as well, for in some cases I need the value of the "Text" property, in other cases the value of the "Value" property; generally speaking, the property I'm interested in might be a function of i.
Cheers.
You could use the ControlsCollection.Find method with the searchAllChildren option set to true
For i As Integer = 1 to N
Dim ctrl = Me.Controls.Find(string.Format("label{0:00}", i), True)
if ctrl IsNot Nothing AndAlso ctrl.Length > 0 Then
row.Item(String.format("col{0:00}", i)) = ctrl(0).Text
End If
Next
An example on how to approach the problem using reflection to set a property that you identify using a string
Dim myLabel As Label = new Label()
Dim prop as PropertyInfo = myLabel.GetType().GetProperty("Text")
prop.SetValue(myLabel, "A Label.Text set with Reflection classes", Nothing)
Dim newText = prop.GetValue(myLabel)
Console.WriteLine(newText)

Refer to forms controls using variable

I've seen many threads on this, but I'm pretty much lost.
For the example below, I have 3 ComboBoxes (cbx_example0, cbx_example1, cbx_example2) located on three TabPages (index 0, 1, 2), respectively. I'd like set the value of the variable myVariable based on the ComboBox on the selected TabPage.
However, I can't seem to figure out how to refer to the ComboBox using a variable. It seems like it should be straightforward, but I guess not. No matter what I do, I get a NullReferenceException.
Function to get TabPage Index number (returns 0 for this example)
Function getTabIndex()
Dim currentTabIndex As Int32 = frm_Main.TabControl1.SelectedIndex
Return currentTabIndex
End Function
Attempt 1 to refer to ComboBox with variable
Dim myVariable As String
Dim i As Integer = getTabIndex
myVariable = frm_Main.Controls("cbx_example" & i).Text
Attempt 2 to refer to ComboBox with variable
Dim cbx_example0 As New ComboBox
Dim i As Integer = getTabIndex()
Dim name As String = "cbx_example" & i.ToString
cbx_example = frm_Main.Controls.Item(name)
myVariable = cbx_example.Text
Your problem is that you think that your cbo is located on the form, while in reality it is on the tabpage. Instead of
cbx_example = frm_Main.Controls.Item(name)
use (for example)
cbx_example = frm_Main.TabPage1.Controls.Item(name)
Keep in mind that your combo is probably not on tab itself but on the tabpage
On another note, I see no need for getTabIndex(). And another way to get any control within hierarchy of your form is to use
form.Controls.Find(key, searchAllChildren)