How to get the value of a textbox from sa MDI form Groupbox? - vb.net

I'm new to vb.net and always searching for solution. My forms involved are MainMenu, poCustom, and rdlcForm. All are working well until I got a new look with MDI Forms.
My "New" MainMenu are now containing the poCustom into a Groupbox. Which I searched the code as
For Each f As Form In Application.OpenForms
If TypeOf f Is poCustom Then
f.Activate()
Return
End If
Next
Dim ch As New poCustom
ch.TopLevel = False
ch.Visible = True
ch.StartPosition = FormStartPosition.Manual
Dim leftStart As Integer = 1220 - (ch.Width + (SystemInformation.Border3DSize.Width * 2))
Dim topStart As Integer = 670 - (ch.Height + (SystemInformation.Border3DSize.Height * 2))
ch.Location = New Point(leftStart, topStart)
GroupBox1.Controls.Add(ch)
Problem: The rdlcForm(report) cannot get the value of textboxes in poCustom form. Code below:
Private Sub rptPOView2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim rptParam1(11) As Microsoft.Reporting.WinForms.ReportParameter
rptParam1(0) = New Microsoft.Reporting.WinForms.ReportParameter("rptDate", poCustom.Label1.Text)
rptParam1(1) = New Microsoft.Reporting.WinForms.ReportParameter("rptREF", poCustom.Label5.Text)
rptParam1(2) = New Microsoft.Reporting.WinForms.ReportParameter("rptCompany", poCustom.CompanyName.Text)
rptParam1(3) = New Microsoft.Reporting.WinForms.ReportParameter("rptQTY", poCustom.txBoxQTY.Text)
rptParam1(4) = New Microsoft.Reporting.WinForms.ReportParameter("rptUOM", poCustom.txBoxUOM.Text)
rptParam1(5) = New Microsoft.Reporting.WinForms.ReportParameter("rptDesciption", poCustom.txBoxDesc.Text)
rptParam1(6) = New Microsoft.Reporting.WinForms.ReportParameter("rptUnit", poCustom.txBoxUnit.Text)
rptParam1(7) = New Microsoft.Reporting.WinForms.ReportParameter("rptTotal", poCustom.txBoxTotal.Text)
rptParam1(8) = New Microsoft.Reporting.WinForms.ReportParameter("rptSubTotal", poCustom.Label25.Text)
rptParam1(9) = New Microsoft.Reporting.WinForms.ReportParameter("rptVAT", poCustom.Label26.Text)
rptParam1(10) = New Microsoft.Reporting.WinForms.ReportParameter("rptTotalAmount", poCustom.Label27.Text)
rptParam1(11) = New Microsoft.Reporting.WinForms.ReportParameter("rptRequest", poCustom.Label30.Text)
ReportViewer1.LocalReport.SetParameters(rptParam1)
Me.ReportViewer1.RefreshReport()
TextBox1.Text = poCustom.CompanyName.Text
End Sub
Which happens to work without using MDI Forms. I would like to know the cause of the problem for future use. Thank you in advance!

You are using two different instances of poCustom. ch is the first, and you populate its textboxes. But on the rptPOView2_Load event, you are using the other instance, which contains textboxes that has no value yet. One way to fix the problem is to use poCustom itself and not ch.
poCustom.TopLevel = False
poCustom.Visible = True
poCustom.StartPosition = FormStartPosition.Manual
Dim leftStart As Integer = 1220 - (ch.Width + (SystemInformation.Border3DSize.Width * 2))
Dim topStart As Integer = 670 - (ch.Height + (SystemInformation.Border3DSize.Height * 2))
poCustom.Location = New Point(leftStart, topStart)
GroupBox1.Controls.Add(poCustom)

Related

How do i get data from a textbox that is made during the runtime of the program?

this is my code its the start of a customer details editing system for my course work
Public Class editCustomerFields
Dim textbox As New TextBox
Private Sub editCustomerFields_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim updownLBL As Integer = 55
Dim updownTXT As Integer = 80
Dim leftRight As Integer = 30
For i = 0 To globalVariables.countForCustomerDetails - 1
Dim label As New Label
label.Size = New System.Drawing.Size(159, 23)
label.Location = New System.Drawing.Point(leftRight, updownLBL)
label.Text = globalVariables.fieldsCustomerDetailsArray(globalVariables.editCustomerDetailsTxtNamesList.Item(i))
label.Name = globalVariables.fieldsCustomerDetailsArray(globalVariables.editCustomerDetailsTxtNamesList.Item(i))
Me.Controls.Add(label)
TextBox.Size = New System.Drawing.Size(315, 30)
TextBox.Location = New System.Drawing.Point(leftRight, updownTXT)
textbox.Name = globalVariables.fieldsCustomerDetailsArray(globalVariables.editCustomerDetailsTxtNamesList.Item(i))
MsgBox(TextBox.Name)
Me.Controls.Add(textbox)
globalVariables.txtEditCustomerDetailsArray(i) = textbox.Name
updownLBL += 60
updownTXT += 60
If updownTXT >= 500 Then
leftRight = 350
updownTXT = 80
updownLBL = 55
End If
Next
End Sub
End Class
i have a bunch of checkboxes that the user selects that correspond to the different fields in the database. then the program takes the input and on another form displays textboxes and labels for the user to enter data into. How do I get the data entered in the textbox?
fieldsCustomerDetailsArray is an array of the field names ("username","password" etc)
editCustomerDetailsTxtNamesList is a list of the checkboxes for the array to use

How to dynamicallty create multiple controls at runtime

I am trying to add multiple labels to a userform at runtime
It's for the player names of a board game; and until the game starts the number of players are not known. I have managed to figure out for myself how to use the dynamic array function to create the list of players. I used a For.....Next loop to add the player names. I thought I could do that to add the labels to the form, but it only adds one. Depending on where the new control type is declared, it either adds the first player only, or the last player
This code produces one label only within the groupbox, the last player
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Players_Num As Integer = InputBox("Enter the number of players")
Dim Players(Players_Num) As String
Dim newText As New Label
For i = 0 To Players_Num - 1
Players(i) = InputBox("Enter player name")
Next
'This piece of code was jsut for me to test that I was successfully using a For...Loop
'to add the players names, and will be deleted later on
For x = 0 To Players_Num - 1
MessageBox.Show(Players(x))
Next
For z = 0 To Players_Num - 1
newText.Name = "txt" & Players(z)
newText.Text = Players(z)
newText.Size = New Size(170, 20)
newText.Location = New Point(12 + 5, 12 + 5)
GroupBox1.Controls.Add(newText)
Next
End Sub
End Class
This one places only the first player
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Players_Num As Integer = InputBox("Enter the number of players")
Dim Players(Players_Num) As String
For i = 0 To Players_Num - 1
Players(i) = InputBox("Enter player name")
Next
'This piece of code was jsut for me to test that I was successfully using a For...Loop
'to add the players names, and will be deleted later on
For x = 0 To Players_Num - 1
MessageBox.Show(Players(x))
Next
For z = 0 To Players_Num - 1
Dim newText As New Label
newText.Name = "txt" & Players(z)
newText.Text = Players(z)
newText.Size = New Size(170, 20)
newText.Location = New Point(12 + 5, 12 + 5)
GroupBox1.Controls.Add(newText)
Next
End Sub
End Class
I've tried this in vs 2015 and 2019 Community
Where is it going wrong?
From the looks of the code, you are correctly creating the controls but their location is the same for all of them, essentially, they are being place one of top of the other, the first is hidden with the second, which is hidden with the third.
The line
newText.Location = New Point(12 + 5, 12 + 5)
needs to be modified to place the labels at different locations.
Perhaps, something like:
newText.Location = New Point(12 + 5, 12 + (z * 25))
This will vertically align the labels with a gap of 25 between them
You are placing them all in the same location
newText.Location = New Point(12 + 5, 12 + 5)
Use your 'z' index to place them at different locations in order to be able to see them
For me it is easier to contain controls in a TableLayoutPanel then add the TLP to what ever control collection, such as a GroupBox This way you can couple a Label with TextBox, for example. Here's an example how you can create controls from a DataTable. In your case you would only need 1 ColumnStyle for labels, I just thought I would show you a good practice for future shortcuts. (I rarely use the designer to place controls)
'Start test data
Dim DtTable As New DataTable
With DtTable
Dim NewDtRow As DataRow = .NewRow
For i As Integer = 0 To 25
Dim DtCol As New DataColumn With {.ColumnName = "Col" & i, .DataType = GetType(String)}
.Columns.Add(DtCol)
NewDtRow(DtCol.ColumnName) = "Test" & i
Next
.Rows.Add(NewDtRow)
End With
'End test data
Dim TLP1 As New TableLayoutPanel With {.Name = "TlpFields"}
With TLP1
.BorderStyle = BorderStyle.Fixed3D
.CellBorderStyle = TableLayoutPanelCellBorderStyle.Inset
.AutoScroll = True
.AutoSize = True
.RowStyles.Clear()
.ColumnStyles.Clear()
.Dock = DockStyle.Fill
.ColumnCount = 2
.ColumnStyles.Add(New ColumnStyle With {.SizeType = SizeType.AutoSize})
End With
For Each DtCol As DataColumn In DtTable.Columns
With TLP1
.RowCount += 1
.RowStyles.Add(New RowStyle With {.SizeType = SizeType.AutoSize})
'create labels
.Controls.Add(New Label With {
.Text = DtCol.ColumnName,
.Anchor = AnchorStyles.Right}, 0, .RowCount)
'create textboxs
Dim TxtBox As New TextBox With {
.Name = "TextBox" & DtCol.ColumnName,
.Size = New Size(170, 20),
.Anchor = AnchorStyles.Left}
'add binding
TxtBox.DataBindings.Add("Text", DtTable, DtCol.ColumnName)
.Controls.Add(TxtBox, 1, .RowCount)
End With
Next
Controls.Add(TLP1)

Read data from dynamically created text-box

I'm trying to collect data after creating dynamic text-box with vb.net
Private Sub btn_OK_lines_number_Click(sender As Object, e As EventArgs)
Handles btn_OK_lines_number.Click
Dim i As Integer
Dim x As Integer
Dim Z As Integer
Z = 150
If IsNumeric(txt_lines_number.Text) Then
Int32.TryParse(txt_lines_number.Text, x)
For i = 1 To x
Dim newTB As New TextBox
Dim newLB As New Label
newLB.Name = "lbl_workstation_number_line" & i
newLB.Text = "Nbr Work Station in Line" & i
newLB.Size = New Size(190, 20)
newLB.ForeColor = Color.White
newLB.Font = New Font("consolas", 12, FontStyle.Regular, GraphicsUnit.Pixel)
newLB.Location = New Point(20, Z + i * 30)
newTB.Name = "Textbox" & i
newTB.Size = New Size(170, 20)
newTB.Location = New Point(200, Z + i * 30)
Me.Controls.Add(newTB)
Me.Controls.Add(newLB)
Next
i = i + 1
Else
MessageBox.Show("please enter a number")
txt_lines_number.Text = ""
End If
End Sub
Let's say you just have one row, and only create one TextBox. You set the name here:
newTB.Name = "Textbox" & i
where the resulting TextBox is named Textbox1. The problem is you can't just reference the identifier Textbox1 directly in your code, as you do with txt_lines_number. You can't even reference it as a member of the class (Me.Textbox1). This name didn't exist at compile time, and so it's not an identifier you can use, and it's not a member of the class at all. There was never a matching Dim statement for that name.
What you can do, though, is look again in the Controls collection where you added the TextBox to the form:
Me.Controls("Textbox1")
or
Me.Controls("Textbox1").Text
You may also need to cast the value to a TextBox:
Dim box As TextBox = DirectCast(Me.Controls("Textbox1"), TextBox)
MessageBox.Show(box.Text)
Remember that case matters here.
Further saving this in a DB is out of scope for one question. There are as many ways to do that as there are programmers in the world. You should make your own attempt first, and come back here with a new question when you run into specific problems.
Thank you,
this is my attempt and it is done !
Dim userInput As TextBox = Form1.Controls.Item("TextBox" & i.ToString)
mycommand.Parameters.AddWithValue("#workstation", userInput.Text)
:D
Because you creating dynamic amount of input controls, right tool for the job will be DataGridView control.
Create a class to represent your data
Public Class LineInfo
Public Property Number As Integer
Public Property WorkStationNumber As Integer
End Class
Create `DataGridView in the form designer.
Private Sub btn_OK_lines_number_Click(sender As Object, e As EventArgs) Handles btn_OK_lines_number.Click
Dim linesAmount As Integer
If Integer.TryParse(txt_lines_number.Text, linesAmount) = False Then
MessageBox.Show("please enter a number")
txt_lines_number.Text = ""
Exit Sub
End If
' Create class instance for every line
Dim lines =
Enumerable.Range(1, linesAmount)
.Select(Function(i) New LineInfo With { .Number = i })
.ToList()
'Set lines as DataSource to the DataGridView
Me.DataGridView1.DataSource = lines
End Sub
DataGridView will display all lines and provide input fields to update work station numbers.
You can access updated lines later by casting DataSource back to the List
Dim lines = DirectCast(Me.DataGridView1.DataSource, List(Of LineInfo))
' Now you can access all data and save it to the database
Dim parameters =
lines.Select(Function(line)
Return new SqlParameter With
{
.ParameterName = $"#workstation{line.Number}",
.SqlDbType = SqlDbType.Int,
.Value = line.WorkStationNumber
}
End Function)
.ToList()
myCommand.Parameters.AddRange(parameters)
You can freely change style, font colors of different columns in the datagridview.

select a different value to multiple comboboxes with the same datasource

It seems as the same problem like in many other posts here and elsewhere.
But everything I tried so far... failed glamorously.
Let me explain:
In the first snippet I populate datagridview with one blank row and create a combobox for each column of this same datagridview. All comboboxes are bind to the same bindingsource. The code is written in this way to allow creating as many comboboxes as there are columns in the datagridview. The number of columns may be different each time.
The problem is that when I change value of the first combobox all others are changed to the same value. And that is not what I'd like to achieve. Now here's what I've tried so far.
CODE1
Private Sub BT_paste_data_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_paste_data.Click
DGV.Rows.Add()
Dim rect As Rectangle
For i = 0 To DGV.Columns.Count - 1
Dim cbc as combobox
cbc = New ComboBox
cbc.Name = i.ToString
DGV.Controls.Add(cbc)
cbc.Visible = True
cbc.BringToFront()
cbc.DataSource = datastringsBindingSource
cbc.ValueMember = "id_data"
cbc.DisplayMember = "data"
cbc.SelectedItem = 9
cbc.Text = "Don't add"
cbc.FlatStyle = FlatStyle.Flat
cbc.BackColor = SystemColors.Menu
cbc.ForeColor = Color.FromArgb(64, 64, 64)
cbc.Font = New Font(DGV.Font, FontHeight = 8.25)
rect = DGV.GetCellDisplayRectangle(i, 0, False)
cbc.Left = rect.Left
cbc.Top = rect.Top
DGV = 20
Next
End If
End Sub
The code above produces following...
picture of comboboxes after load
and when I select a different item from the list in the first combobox all others are also changed.
So I searched the web and found that same bindingsource could be the problem.
So I changed the code some to bind comboboxes to a different bindingsource each time.
CODE2
Private Sub BT_paste_data_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_paste_data.Click
DGV.Rows.Add()
Dim rect As Rectangle
For i = 0 To DGV.Columns.Count - 1
Dim cbc as combobox
cbc = New ComboBox
cbc.Name = i.ToString
DGV.Controls.Add(cbc)
cbc.Visible = True
cbc.BringToFront()
'following two lines were added and the third changed accordingly
Dim bs As New BindingSource
bs = datastringsBindingSource
cbc.DataSource = bs
cbc.DataSource = bs
cbc.ValueMember = "id_data"
cbc.DisplayMember = "data"
cbc.SelectedItem = 9
cbc.Text = "Dont add"
cbc.FlatStyle = FlatStyle.Flat
cbc.BackColor = SystemColors.Menu
cbc.ForeColor = Color.FromArgb(64, 64, 64)
cbc.Font = New Font(DGV.Font, FontHeight = 8.25)
rect = DGV.GetCellDisplayRectangle(i, 0, False)
cbc.Left = rect.Left
cbc.Top = rect.Top
DGV = 20
Next
End If
End Sub
I get same result as with CODE1. Comboboxes are created fine but when value in one of them is changed all of them get changed accordingly.
So I thought that perhaps creating all comboboxes like 'cbc' (although they have different names (0,1,2,3) could be the problem.
At this point I'm opened for any suggestions.
following the suggestion from fabio I changed a part of the CODE2:
Private Sub BT_paste_data_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_paste_data.Click
DGV.Rows.Add()
Dim rect As Rectangle
For i = 0 To DGV.Columns.Count - 1
Dim cbc as combobox
cbc = New ComboBox
cbc.Name = i.ToString
DGV.Controls.Add(cbc)
cbc.Visible = True
cbc.BringToFront()
'following two lines were added and the third changed accordingly
Dim bs As New BindingSource
bs = datastringsBindingSource
'next line was suggested by fabio but the result is still the same
cbc.BindingContext = New BindingContext()
cbc.DataSource = bs
cbc.ValueMember = "id_data"
cbc.DisplayMember = "data"
cbc.SelectedItem = 9
cbc.Text = "Dont add"
cbc.FlatStyle = FlatStyle.Flat
cbc.BackColor = SystemColors.Menu
cbc.ForeColor = Color.FromArgb(64, 64, 64)
cbc.Font = New Font(DGV.Font, FontHeight = 8.25)
rect = DGV.GetCellDisplayRectangle(i, 0, False)
cbc.Left = rect.Left
cbc.Top = rect.Top
DGV = 20
Next
End If
End Sub
OK I got it.
Since 'new bindingcontext' didn't work and I was now more and more convinced that duplicating bindingsource would solve the problem, I checked for solutions on bindingsource duplication and found out following line should be changed. So...
Dim bs As new Bindingsource
should become:
Dim bs As new Bindingsource(datastringsBindingSource.Datasource, datastringsBindingSource.DataMember)
Therefore my final working solution is for now:
Private Sub BT_paste_data_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_paste_data.Click
DGV.Rows.Add()
Dim rect As Rectangle
For i = 0 To DGV.Columns.Count - 1
Dim cbc as combobox
cbc = New ComboBox
cbc.Name = i.ToString
DGV.Controls.Add(cbc)
cbc.Visible = True
cbc.BringToFront()
'here is the line that was changed
Dim bs As new Bindingsource(datastringsBindingSource.Datasource, datastringsBindingSource.DataMember)
bs = datastringsBindingSource
'next line was suggested by fabio but the result is still the same
'cbc.BindingContext = New BindingContext() - sorry fabio, this line seems to be irelevant
cbc.DataSource = bs
cbc.ValueMember = "id_data"
cbc.DisplayMember = "data"
cbc.SelectedItem = 9
cbc.Text = "Dont add"
cbc.FlatStyle = FlatStyle.Flat
cbc.BackColor = SystemColors.Menu
cbc.ForeColor = Color.FromArgb(64, 64, 64)
cbc.Font = New Font(DGV.Font, FontHeight = 8.25)
rect = DGV.GetCellDisplayRectangle(i, 0, False)
cbc.Left = rect.Left
cbc.Top = rect.Top
DGV = 20
Next
End Sub

Trouble with Timer_tick not stopping

I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer