select a different value to multiple comboboxes with the same datasource - vb.net

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

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)

How to get the value of a textbox from sa MDI form Groupbox?

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)

vb.net layering of controls not working properly

I simply want to add three controls to my form. The first two show up, but the third does not. I do not understand why this behavior is happening. I have tried using .bringToFront(), but I end up with the same results. I also tried using Me.controls.setChildIndex() but that does not help either.
I am at a loss. I must be doing something wrong. Please help.
Thanks.
This is my code:
' Add the label
' ------------------
Dim menu_label As New Label
menu_label.Text = "Menu"
menu_label.Location = New Point(50, 20)
menu_label.Width = 50
menu_label.Font = New Font(main_font, main_font_size, FontStyle.Regular)
menu_label.ForeColor = Color.White
Me.Controls.Add(menu_label)
' create the image
' ---------------
Dim logo As New PictureBox
Dim logo_image As Image
logo_image = My.Resources.logo
logo.Image = logo_image
logo.Width = 30
logo.Height = 30
logo.Left = 5
logo.Top = 0
Me.Controls.Add(logo)
' add a line
' ----------
Dim line As New Panel
line.Height = 1
line.Width = Me.Width
line.BackColor = Color.Red
line.Location = New Point(0, 32)
Me.Controls.Add(line)
' end code
' ---------------------------------
Only the first two items show up no matter which order I put them in. So I either get just the logo and the menu label, or just the logo and the line, or just the line and the menu label. It's nuts!
So I tried:
Me.Controls.SetChildIndex(logo, 0)
Me.Controls.SetChildIndex(menu_label, 1)
Me.Controls.SetChildIndex(line, 2)
Whichever item gets assigned to level 2 never shows up.
I also tested and it worked fine for me. Changed the form backcolor to black so you can see the results better:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
' Add the label
' ------------------
Dim menu_label As New Label
menu_label.Text = "Menu"
menu_label.Location = New Point(50, 20)
menu_label.Width = 50
'menu_label.Font = New Font(main_font, main_font_size, FontStyle.Regular)
menu_label.ForeColor = Color.White
Me.Controls.Add(menu_label)
' create the image
' ---------------
Dim logo As New PictureBox
Dim logo_image As Image
'logo_image = My.Resources.logo
'logo.Image = logo_image
logo.BackColor = Color.Yellow
logo.Width = 30
logo.Height = 30
logo.Left = 5
logo.Top = 0
Me.Controls.Add(logo)
' add a line
' ----------
Dim line As New Panel
line.Height = 1
line.Width = Me.Width
line.BackColor = Color.Red
line.Location = New Point(0, 32)
Me.Controls.Add(line)
Me.BackColor = Color.Black
End Sub
What else is on your form? Perhaps you could post a screenshot?

Adding checkbox to datagridview column header, not aligning properly

Im trying to add a checkbox to a specific datagridview column header, I found some code online to help but it's not aligning properly and I'm not really sure how to fix it.
Below is an image of the problem and the code, any help would be greatly appreciated!
P.S. I think it might be something to do with properties but I've played around with them but not been successful.
Private checkboxHeader231 As CheckBox
Private Sub show_chkBox()
Dim rect As Rectangle = DataGridView1.GetCellDisplayRectangle(columnIndexOfCheckBox, -1, True)
' set checkbox header to center of header cell. +1 pixel to position
rect.Y = 3
rect.X = rect.Location.X + 8 + (rect.Width / 4)
checkboxHeader231 = New CheckBox()
With checkboxHeader231
.BackColor = Color.Transparent
End With
checkboxHeader231.Name = "checkboxHeader1"
checkboxHeader231.Size = New Size(18, 18)
checkboxHeader231.Location = rect.Location
AddHandler checkboxHeader231.CheckedChanged, AddressOf checkboxHeader231_CheckedChanged
DataGridView1.Controls.Add(checkboxHeader231)
End Sub
Private Sub checkboxHeader231_CheckedChanged(sender As System.Object, e As System.EventArgs)
Dim headerBox As CheckBox = DirectCast(DataGridView1.Controls.Find("checkboxHeader1", True)(0), CheckBox)
For Each row As DataGridViewRow In DataGridView1.Rows
row.Cells(columnIndexOfCheckBox).Value = headerBox.Checked
Next
End Sub
This is my first entry, but I think this is what youre looking for. I tested it and it worked on my datagrid. You were using the width for the rectangle, youll need it for the column width instead. I set the column header to 4, but you would replace the 4 with your column you want to use I put it in two ways, one with a four loop, the other just as single lines. Tell me if this worked for you:
Dim rect As Rectangle = DataGridView1.GetCellDisplayRectangle(4, -1, True) ' replace 4
rect.Y = 3
Dim sum = DataGridView1.Columns(0).Width
'for this area write a for loop to find the width of each column except for the last line which you manually do
'
'
'For i As Integer = 1 To 4 - 1 Step 1 ' replace 4
'sum = sum + DataGridView1.Columns(i).Width
'Next
sum = sum + DataGridView1.Columns(1).Width
sum = sum + DataGridView1.Columns(2).Width
sum = sum + DataGridView1.Columns(3).Width
' stop here and add the last line by hand here
sum = sum + (DataGridView1.Columns(4).Width / 2) + 35 ' used in both cases ' replace 4
rect.X = sum
checkboxHeader231 = New CheckBox()
With checkboxHeader231
.BackColor = Color.Transparent
End With
checkboxHeader231.Name = "checkboxHeader1"
checkboxHeader231.Size = New Size(18, 18)
checkboxHeader231.Location = rect.Location
AddHandler checkboxHeader231.CheckedChanged, AddressOf checkboxHeader231_CheckedChanged
DataGridView1.Controls.Add(checkboxHeader231)
Private headerBox As CheckBox
Private Sub show_checkBox()
Dim checkboxHeader As CheckBox = New CheckBox()
Dim rect As Rectangle = PendingApprovalServiceListingDataGridView.GetCellDisplayRectangle(4, -1, True)
rect.X = 20
rect.Y = 12
With checkboxHeader
.BackColor = Color.Transparent
End With
checkboxHeader.Name = "checkboxHeader"
checkboxHeader.Size = New Size(14, 14)
checkboxHeader.Location = rect.Location
AddHandler checkboxHeader.CheckedChanged, AddressOf checkboxHeader_CheckedChanged
PendingApprovalServiceListingDataGridView.Controls.Add(checkboxHeader)
End Sub
Private Sub checkboxHeader_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
headerBox = DirectCast(PendingApprovalServiceListingDataGridView.Controls.Find("checkboxHeader", True)(0), CheckBox)
For Each row As DataGridViewRow In PendingApprovalServiceListingDataGridView.Rows
row.Cells(0).Value = headerBox.Checked
Next
End Sub