How to declare textbox as a global variable? - vb.net

I have declared a textbox via button click:
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim txtbox As New TextBox()
txtbox.Location = New Point(200, 0)
txtbox.Height = 20
txtbox.Width = 100
tp.Controls.Add(txtbox)
Now I want a label in another sub to display the content of the textbox. My first attempt was:
label.Text = txtbox.text
But that didn't work because my textbox was declared locally and I have no idea how to declare this as a global variable...

You should try to avoid global variables if there are workarounds for the task you have. For example you can retrieve your textbox from the Controls collection where you have added it. You just need something to help you locate the right textbox.
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim txtbox As New TextBox()
txtbox.Location = New Point(200, 0)
txtbox.Height = 20
txtbox.Width = 100
txtbox.Name = "MyImportantTextBox"
tp.Controls.Add(txtbox)
Now when you want to retrieve it
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim textbox = tp.Controls.
OfType(Of TextBox).
FirstOrDefault(Function(x) x.Name = "MyImportantTextBox")
if textbox IsNot Nothing Then
label.Text = textbox.Text
End If
There is also another simpler possibility, add an handler for the textbox TextChanged event and when you type something in that textbox reflect the content in the label.
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim txtbox As New TextBox()
txtbox.Location = New Point(200, 0)
txtbox.Height = 20
txtbox.Width = 100
AddHandler txtbox.TextChanged, AddressOf OnMyTextBoxChange
tp.Controls.Add(txtbox)
And add an event handler for the txtbox like this
Sub OnMyTextBoxChange(sender as Object, e as EventArgs)
Dim txtbox = DirectCast(sender, TextBox)
label.Text = txtbox.Text
End Sub

The issue is you never set the text property. Try this:
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim txtbox As New TextBox()
txtbox.Text = "Some Text"
txtbox.Location = New Point(200, 0)
txtbox.Height = 20
txtbox.Width = 100
tp.Controls.Add(txtbox)
I added one line of code to your example.

Bryan had a good idea.
My personal choice would be declaring a global string variable and during your button click procedure assigning it the value of your textbox.

Related

how to add some textbox with Code

i have trouble with this
Click Here for picture
The Code
Dim Tex1 As TextBox = Nothing
Dim Tex2 As TextBox = Nothing
Tex1 = New Windows.Forms.TextBox
Tex1.Name = "TextBox"
Tex1.Location = New System.Drawing.Point(12, 119)
Tex1.Size = TextBox1.Size
Tex1.TabIndex = 4
Tex2 = New Windows.Forms.TextBox
Tex2.Name = "TextBox"
Tex2.Location = New System.Drawing.Point(110, 119)
Tex2.Size = TextBox2.Size
Tex2.TabIndex = 5
Me.Controls.Add(Tex1)
Me.Controls.Add(Tex2)
i want to add the new textbox with clicking the picture box, like this
Click Here for Picture
but when i click the "add Picture Box" the textbox not appear
please, anyone help me ?
If you want to have the ability to add textboxes to your form then this is what you should do. First you will need to identify the button that you are going to use for this insertion event. I would assume the green plus symbol.
Then I would create a mouse event action like this:
Public Sub Mouse_Click(sender As Object, e As EventArgs) Handles MyButton.Click
' Some action...
End Sub
From there you will be able to insert your code into the click event like this:
Public Sub Mouse_Click(sender As Object, e As EventArgs) Handles MyButton.Click
Dim Tex1 As TextBox = Nothing
Dim Tex2 As TextBox = Nothing
Tex1 = New Windows.Forms.TextBox
Tex1.Name = "TextBox"
Tex1.Location = New System.Drawing.Point(12, 119)
Tex1.Size = TextBox1.Size
Tex1.TabIndex = 4
Tex2 = New Windows.Forms.TextBox
Tex2.Name = "TextBox"
Tex2.Location = New System.Drawing.Point(110, 119)
Tex2.Size = TextBox2.Size
Tex2.TabIndex = 5
Me.Controls.Add(Tex1)
Me.Controls.Add(Tex2)
End Sub
Now there is still a big issue with this code, the location of the textboxes. The reason this is an issue is because they are static, meaning they will always appear in the same spot so, one solution is to declare a global Point() to maintain the location of the newest textbox like this:
Dim tbLocation1 As Point = New Point(12, 199)
Dim tbLocation2 As Point = New Point(110, 199)
From there all you would then need to do is have some sort of margin amount that you want to move the textboxes by like this:
Dim marginAmt As Int32 = 30
Now that all of the pieces are present lets put it together:
Dim tbLocation1 As Point = New Point(12, 199)
Dim tbLocation2 As Point = New Point(110, 199)
Dim marginAmt As Int32 = 30
Public Sub Mouse_Click(sender As Object, e As EventArgs) Handles MyButton.Click
Dim Tex1 As TextBox = New Windows.Forms.TextBox
Dim Tex2 As TextBox = New Windows.Forms.TextBox
' Modifies Tex1
Tex1.Name = "TextBox"
Tex1.Location = tbLocation1
Tex1.Size = TextBox1.Size
Tex1.TabIndex = 4
' Modifies Tex2
Tex2.Name = "TextBox"
Tex2.Location = tbLocation2
Tex2.Size = TextBox2.Size
Tex2.TabIndex = 5
' Updates form
Me.Controls.Add(Tex1)
Me.Controls.Add(Tex2)
' Updates the point locations
tbLocation1 = New Point(tbLocation1.X, tbLocation1.Y + marginAmt)
tbLocation2 = New Point(tbLocation2.X, tbLocation2.Y + marginAmt)
End Sub
Now you just need to connect this event action to the button that you desire.

VB.NET Getting Value On Dynamic Control

I am new to VB and run into some problems.
I have created sub routine that will automatically add a control to a panelcontrol each time i click on the button, so it can create as many as i want.
Here is the code for the subroutine.
Private Sub CreateControl()
'CREATE TEXTBOX ITEMNO
Dim i_Itemno As Integer = TextEditItemno.Length
ReDim Preserve TextEditItemno(i_Itemno)
TextEditItemno(i_Itemno) = New TextEdit
With TextEditItemno(i_Itemno)
.Name = "Txtitemno" & i_Itemno.ToString()
If TextEditItemno.Length < 2 Then
.SetBounds(0, 0, 32, 20)
Else
.Left = TextEditItemno(i_Itemno - 1).Left
.Top = TextEditItemno(i_Itemno - 1).Top + TextEditItemno(i_Itemno - 1).Height + 4
.Size = TextEditItemno(i_Itemno - 1).Size
End If
.Tag = i_Itemno
End With
AddHandler TextEditItemno(i_Itemno).TextChanged, AddressOf TextEditItemno_TextChanged
PanelControl5.Controls.Add(TextEditItemno(i_Itemno))
'CREATE TEXTBOX PRICE
Dim i_Price As Integer = TextEditPrice.Length
ReDim Preserve TextEditPrice((i_Price))
Dim PriceX As Int16 = LblHarga.Location.X
TextEditPrice(i_Price) = New TextEdit
With TextEditPrice(i_Price)
.Name = "Txtprice" & i_Price.ToString()
If TextEditSatuan.Length < 2 Then
.SetBounds(PriceX, 0, 70, 20)
Else
.Left = TextEditPrice(i_Price - 1).Left
.Top = TextEditPrice(i_Price - 1).Top + TextEditPrice(i_Price - 1).Height + 4
.Size = TextEditPrice(i_Price - 1).Size
End If
.Tag = i_Price
End With
AddHandler TextEditPrice(i_Price).TextChanged, AddressOf TextEditPrice_TextChanged
PanelControl5.Controls.Add(TextEditPrice(i_Price))
End Sub
And i call it in a button click.
Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click
CreateControl()
End Sub
Now what i am looking for is how to loop and get the value of those textboxes no matter how many textboxex i have create.
For i As Integer = 0 To TextEditItemno.Length - 1
' code to get the value of each textbox
Next
Thank you
This code goes in to your loop and gets the value of each textbox based on i.
Dim Text as String = TextEditItemno(i).Text
You may also be better served by using a List(of Textbox) rather than an array of textboxes. You don't need to worry about redimming the array, you can just do MyListOfTextboxes.Add(TheNewTextBox). You can still retrieve the value of each textbox the same way as the array.

Remove LineShape from Windows Form, LineShape and ShapeContainer Arrays

I am using the code below to add multiple LineShape controls to a Windows Form. Note the globally declared mLineShapes() and mShapeContainter() arrays (at bottom of code) which store each new LineShape object once it's created.
At present, I have been unsuccessful at removing a given LineShape control from the form (even if I know its array index), and also cannot removing an array element without causing a Nothing for the removed element. Obviously, once I remove the element from these arrays, it requires that all the remaining elements with greater indices are copied to lower values to fill in the Nothing voided element. Given these circumstances, can lists be used instead of the mLineShapes() and mShapeContainer() arrays?
enter code here' create new ShapeContainer
Dim sSCTemp As New ShapeContainer
' add ShapeContainer to Form
sSCTemp.Parent = Me
' create new LineShape
Dim sLSTemp As New LineShape
sLSTemp.BorderColor = Color.Black
sLSTemp.BorderWidth = 2
sLSTemp.Cursor = Cursors.Cross
' add LineShape to ShapeContainer
sLSTemp.Parent = sSCTemp
' set starting and ending coordinates for the line
sLSTemp.StartPoint = New System.Drawing.Point(siSCCount * 20, 60 + siSCCount * 60)
sLSTemp.EndPoint = New System.Drawing.Point(100 + siSCCount * 20, 110 + siSCCount * 60)
' set new LineShape to top of z-order
sLSTemp.BringToFront()
sSCTemp.BringToFront()
' connect ContextMenuStrip to LineShape
sLSTemp.ContextMenuStrip = mLsCtm1
' add new LineShape to arrays
ReDim Preserve mLineShapes(siSCCount)
ReDim Preserve mShapeContainer(siSCCount)
mLineShapes(siSCCount) = sLSTemp
mLineShapes(siSCCount).Name = "LineShape" & siSCCount
mShapeContainer(siSCCount) = sSCTemp
mShapeContainer(siSCCount).Name = "ShapeContainer" & siSCCount
In addition to the above, the endpoints of each
LineShape are selected from the arrays so that they can be moved. An example is below:
Dim siSCId As Integer
Dim myShapeContainer As ShapeContainer
myShapeContainer = CType(sender, ShapeContainer)
Dim myLineShape As LineShape
' get index of the actual ShapeContainer in ShapeContainer array
siSCId = Array.IndexOf(mShapeContainer, sender)
If siSCId > -1 Then
myLineShape = mLineShapes(siSCId)
If MouseIsNearBy(myLineShape.EndPoint) Then
myLineShape.BorderColor = Color.Red
NearLineEndPoint = True
End If
If MouseIsNearBy(myLineShape.EndPoint) = False Then
myLineShape.BorderColor = Color.Black
NearLineEndPoint = False
End If
If (dragStartPoint) Then
myLineShape.StartPoint = New Point(oldStartPoint.X + e.X - oldMouseX, oldStartPoint.Y + e.Y - oldMouseY)
End If
End If
Therefore, If I simply add a new LineShape to the form controls without using the mLineShapes() ans mShapeControl() arrays, how can I modify the above code (which finds the LineShape in the storage arrays) so that the line can be modified? I think that if I click on a LineShape, I can get its name using .sourcecontrol or .parent?
UPDATE 5/9/2019
After right clicking on a control on Form1 and selecting the "Link" command from a ContextMenuStrip, the following method (ctmsconnect) is fired to draw a new LineShape control that the user then drags and drops on to the next control in the workflow. Question is, is the list of LineShapes ("Lines") not needed?
(in Form1 class declarations):
Dim SC As New ShapeContainer
Dim Lines As New List(Of LineShape)
Private Sub ctmsconnect_Click(sender As System.Object, e As System.EventArgs) Handles ctmsconnect.Click
mLineWidth = 1
Dim myItem As ToolStripMenuItem = CType(sender, ToolStripMenuItem)
Dim cms As ContextMenuStrip = CType(myItem.Owner, ContextMenuStrip)
Dim x As Integer = cms.SourceControl.Right - 2
Dim y As Integer = cms.SourceControl.Top + (cms.SourceControl.Height / 2 - 12)
Dim LS As New LineShape
NumLineShapes += 1
LS.Name = "LineShape" & NumLineShapes
LS.BorderColor = Color.Black
LS.BorderWidth = 2
'Set starting and ending coordinates for the line
LS.StartPoint = New Point(x, y)
LS.EndPoint = New Point(x + 80, y - 5)
'Set new LineShape to top of z-order
LS.BringToFront()
Dim nxgContextMenuStrip As New ContextMenuStrip
LS.ContextMenuStrip = nxgContextMenuStrip
LS.Tag = "LineShape" & NumLineShapes & "_Delete"
'Attach an event handler for the ContextMenuStrip control's Opening event.
AddHandler nxgContextMenuStrip.Opening, AddressOf cms_Opening
numconnectedlineendpoints += 1
Dim myValues As New List(Of String)
myValues.Add(cms.SourceControl.Name)
DropLineOriginalObjectName = cms.SourceControl.Name
OrigDropControl = cms.SourceControl
myValues.Add(LS.Name)
myValues.Add("linestart")
dicGUIControls.Add(numconnectedlineendpoints, myValues)
Lines.Add(LS)
SC.Shapes.Add(LS)
Me.Refresh()
End Sub
You shouldn't need the arrays, just use the controls collection. Instead of setting the parent of the controls, you should probably add them to the collection:
'sSCTemp.Parent = Me
Me.Controls.Add(sSCTemp)
To remove them, you can reference them by the name property:
If Me.Controls.ContainsKey("ShapeContainer1") Then
Me.Controls.RemoveByKey("ShapeContainer1")
End If
The shape controls inside the ShapeContainer have to be accessed through the Shape collection:
If Me.Controls.ContainsKey("ShapeContainer1") Then
Dim sc As ShapeContainer = DirectCast(Me.Controls("ShapeContainer1"), ShapeContainer)
If sc.Shapes.ContainsKey("LineShape2") Then
sc.Shapes.RemoveAt(sc.Shapes.IndexOfKey("LineShape2"))
End If
End If
Example of reading the StartPoint and EndPoint properties:
Dim sb As New StringBuilder
For Each ls As LineShape In Me.ShapeContainer1.Shapes
sb.AppendLine(ls.StartPoint.ToString & " - " & ls.EndPoint.ToString)
Next
MessageBox.Show(sb.ToString)
Note: ShapeContainer Class makes a special note:
Be careful that you do not create more than one ShapeContainer for each form or container; doing this may introduce unexpected behavior. If you add a design-time line or shape control to a form or container after you write code to create one programmatically, you should modify that code to use the ShapeContainer created by the designer.
Public Class Form1
Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
' Set the form as the parent of the ShapeContainer.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
canvas.Parent = Me
' Set the ShapeContainer as the parent of the LineShape.
End Sub
Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
If RadioButton1.Checked = True Then
Dim line1 As New Microsoft.VisualBasic.PowerPacks.LineShape
line1.Parent = canvas
' Set the starting and ending coordinates for the line.
line1.StartPoint = New System.Drawing.Point(Me.Width / 2, 0)
line1.EndPoint = New System.Drawing.Point(e.X, e.Y)
TextBox1.Text = canvas.Shapes.Count.ToString
line1.Name = "MyShape"
canvas.Shapes.Add(line1)
AddHandler line1.Click, AddressOf LineClick
End If
End Sub
Private Sub LineClick(sender As Object, e As EventArgs)
' Here is where we take the object that is sender from the arguments and cast it to its specific control
If RadioButton2.Checked = True Then
' I could just as easily use
CType(sender, PowerPacks.LineShape).Dispose()
TextBox1.Text = canvas.Shapes.Count
End If
End Sub
End Class

Why do the WordWrap and AutoSize properties on a Text Box behave differently if the text boxes are added dynamically?

I am creating some textboxes dynamically in a custom control (actually is just a panel with a binding source that adds other sub controls at runtime.
In some of those I am setting WordWrap=True because I am expecting large text. But the textbox has only one line. Also I notice that I have to set the property AutoSize to False. When I add dynamically textboxes in a form everything is working fine (even without setting the AutoSize and the WordWrap.
Dim txt as new textbox
txt.Multiline = True
txt.AutoSize = False
txt.Size = New Size(100, 50)
txt.WordWrap = True
txt.Location = New Point(10, 10)
Me.Controls.Add(txt) 'Me is my custom Control
I checked the property WordWrap for the text box after I inserted them (with double click) and it is True.
Any ideas why I face this strange behaviour in my custom control?
Edit:
The problem is that I cannot make my text to wordwrap. So although I set MultiLine to true, AutoSize to false, WordWrap to True, the text is not changing lines. I don't want to add scrollbars.
You could adjust the .Height of the TextBox when its .Text changes:
Public Class Form1
Dim txt As TextBox
Sub maketb()
txt = New TextBox
txt.Multiline = True
txt.Size = New Size(100, 50)
txt.WordWrap = True
txt.Location = New Point(10, 10)
Me.Controls.Add(txt)
End Sub
Sub SetHeight(sender As Object, e As EventArgs)
Dim target = DirectCast(sender, TextBox)
Dim fn = target.Font
Dim gr = target.CreateGraphics()
Dim lrMarginSize = target.Margin.Left + target.Margin.Right
Dim tbMarginSize = target.Margin.Top + target.Margin.Bottom
Dim h = gr.MeasureString(target.Text, fn, target.Width - lrMarginSize).Height + tbMarginSize
target.Height = CInt(Math.Ceiling(h))
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
maketb()
AddHandler txt.TextChanged, AddressOf SetHeight
txt.Text = "dfgd dfd gg hgljhhkjlh jhkkj hkjh hghjg hgjhgz hfjsdhfytu hgjahg ht gretyt jgagury agha gty ajhg ajgx"
End Sub
End Class
Guys I have to apologize.
The error was in my xml (I had MultiLine instead of Multiline), so my textbox was never Multiline.
Thanks for your time, Sorry for spending it without meaning.

Passing arguments from a dynamic control to AddHandler in VB.NET

I'm trying to figure out how to pass information from one form to another using an AddHandler that I create in a dynamic control.
I have a loop something like
Dim I As Integer
For I = 0 To 10
Dim gbNew As New GroupBox()
Dim pbNew As New PictureBox()
Dim llbNew As New Label()
Dim tlbNew As New Label()
Dim olbNew As New Label()
Dim slbNew As New Label()
Dim wlbNew As New Label()
UserName = dt.Rows(I)("UserName").ToString()
Status = dt.Rows(I)("LastJobType").ToString()
JobType = dt.Rows(I)("LastJobType").ToString()
LLocation = dt.Rows(I)("LastLocation").ToString()
TimeIn = dt.Rows(I)("LogInTime")
TimeOut = dt.Rows(I)("LogOutTime")
FlowLayoutPanel1.Controls.Add(gbNew)
gbNew.Controls.Add(llbNew)
llbNew.Visible = True
llbNew.Text = LLocation
llbNew.Font = New Font(llbNew.Font.FontFamily, 6.5)
llbNew.Location = New System.Drawing.Point(3, 25)
llbNew.BorderStyle = BorderStyle.None
llbNew.TextAlign = ContentAlignment.MiddleLeft
llbNew.Size = New Size(80, 15)
gbNew.Size = New System.Drawing.Size(270, 80)
'gbNew.BackColor = System.Drawing.Color.Silver
gbNew.Visible = True
gbNew.Text = UserName & " " & I + 1
AddHandler gbNew.Click, AddressOf ShowForm
Next
The eventhandler fires off a sub ShowForm:
Private Sub ShowForm()
Details.Show()
End Sub
This in turn pops up a form, but I can't figure out how to pass a few needed bits of information from the dynamic generated control to a static control outside the loop.
I was using a static control in a form:
label1.text = "something"
And I opened the new form, and I could read that into the new form using something like
dim info as string = form1.label.text. But since it is dynamic, I don't have a label1.text. Instead, I have a llbNew.Text which seems to be something I can't call from form2 :(
How can I pass information from form1's dynamic control to form2?
Please keep this to VB.NET, not C#, as I barely understand VB.NET let alone trying to brain convert from C# which I have zero knowledge of.
Here's a direction you could take. I hope it is clear:
For I = 0 To 10
(...)
gbNew.Text = UserName & " " & I + 1
gbNew.Tag = dt.Rows(I) ' Any information that you need here
AddHandler gbNew.Click, AddressOf ShowForm '(No changes here)
Next
' Use the appropriate Event Handler signature # the handler Sub
Private Sub ShowForm(sender as Object, e as EventArgs)
Dim groupBoxClicked as GroupBox = TryCast(sender, GroupBox)
If groupBoxClicked IsNot Nothing
Dim detailsForm as New Details()
detailsForm.ParentInformation = groupBoxClicked.Tag
detailsForm.ShowDialog()
End If
End Sub
(...)
Public Class Details ' Your Details Form
Public Property ParentInformation as DataRow
End Class