Capturing an event such as mouse click in Datagridview in VB - vb.net

Update 5/21/17. Thank you for the suggestion of using a Table. That was helpful. I actually figured it out. I made myinputable a global variable by declaring the Dim statement at the top and making it a Datagridview type. Now I can turn it off in the other event that I needed to do it.
I am a novice. I have created a Datagridview in VB 2015 to capture a bunch of data from the use. When the user is finished with the data entry, I want to store the cell values in my variables. I do not know how to capture any event from my dynamically created datagridview "myinputable." My code is below. Please help.
Private Sub inputmodel()
Dim prompt As String
Dim k As Integer
'
' first get the problem title and the number of objectives and alternatives
'
prompt = "Enter problem title: "
title = InputBox(prompt)
prompt = "Enter number of criteria: "
nobj = InputBox(prompt)
prompt = "Enter number of alternatives: "
nalt = InputBox(prompt)
'
' now create the table
'
Dim Myinputable As New DataGridView
Dim combocol As New DataGridViewComboBoxColumn
combocol.Items.AddRange("Increasing", "Decreaing", "Threashold")
For k = 1 To 6
If k <> 2 Then
Dim nc As New DataGridViewTextBoxColumn
nc.Name = ""
Myinputable.Columns.Add(nc)
Else
Myinputable.Columns.AddRange(combocol)
End If
Next k
' now add the rows and place the spreadsheet on the form
Myinputable.Rows.Add(nobj - 1)
Myinputable.Location = New Point(25, 50)
Myinputable.AutoSize = True
Me.Controls.Add(Myinputable)
FlowLayoutPanel1.Visible = True
Myinputable.Columns(0).Name = "Name"
Myinputable.Columns(0).HeaderText = "Name"
Myinputable.Columns(1).Name = "Type"
Myinputable.Columns(1).HeaderText = "Type"
Myinputable.Columns(2).Name = "LThresh"
Myinputable.Columns(2).HeaderText = "Lower Threshold"
'Myinputable.Columns(2).ValueType = co
Myinputable.Columns(3).Name = "UThresh"
Myinputable.Columns(3).HeaderText = "Upper Threshold"
Myinputable.Columns(4).Name = "ABMin"
Myinputable.Columns(4).HeaderText = "Abs. Minimum"
Myinputable.Columns(5).Name = "ABMax"
Myinputable.Columns(5).HeaderText = "Abs. Maximum "
Myinputable.Rows(0).Cells(0).Value = "Help"
If Myinputable.Capture = True Then
MsgBox(" damn ")
End If
End Sub

As #Plutonix suggests, you should start by creating a DataTable. Add columns of the appropriate types to the DataTable and then bind it to the grid, i.e. assign it to the DataSource of your grid, e.g.
Dim table As New DataTable
With table.Columns
.Add("ID", GetType(Integer))
.Add("Name", GetType(String))
End With
DataGridView1.DataSource = table
That will automatically add the appropriate columns to the grid if it doesn't already have any, or you can add the columns in the designer and set their DataPropertyName to tell them which DataColumn to bind to. As the user makes changes in the grid, the data will be automatically pushed to the underlying DataTable.
When you're done, you can access the data via the DataTable and even save the lot to a database with a single call to the Update method of a data adapter if you wish.

Related

How to fill a combobox in a datagridview

I have a datagrid view with 10 columns. It includes 2 checkbox columns followed by a combobox and then a number of text boxes for data entry. I do not have a database to load the combobox drop down but I do have a variable with 19 rows. I have tried a number of methods from SO but haven't been able to get this to work correctly so I can load the combobox for the user to select a value.
The code I've been using is like this. I have tried several different ways that are commented out as well...
' Build datagridview row
'
Dim t1 As New DataTable
For Each col As DataGridViewColumn In dgvMultiSelect.Columns
t1.Columns.Add(col.HeaderText)
Next
Dim dgvcb As New DataTable
dgvcb.Columns.Add("RunID", GetType(String))
For el = 0 To sRunID.Length - 1
dgvcb.Columns.Add(sRunID(el))
RunID.Items.Add(sRunID(el))
Next
' RunID.DataSource = dgvcb
' RunID.DataPropertyName = "dgvcb"
' RunID.DataSource = sRunID
' RunID.DataPropertyName = "sRunID"
'Dim chk As New DataGridViewCheckBoxColumn()
'DataGridView1.Columns.Add(chk)
'chk.HeaderText = "Check Data"
'chk.Name = "chk"
dgvMultiSelect.Rows(0).Cells(0).Value = True
The checkbox works fine (it shows as checked) and I was able to set the combobox value to show but clicking on the dropdown does nothing. I believe the data is in RunID (the column in the dgv.
Well, the answer that worked for me is: I was referencing the datagridviewCOLUMN and not a datagridviewCOMBOBOXcolumn. Thanks to Sai Kalyan Kumar Akshinthala!
' Build datagridview row
Dim dgvcc As DataGridViewComboBoxColumn
dgvcc = dgvMultiSelect.Columns("RunID")
For el = 0 To sRunID.Length - 1
dgvcc.Items.Add(sRunID(el))
dgvMultiSelect.Rows(0).Cells(2).Value = sRunID(el)
Next
Maybe next time you'll try to understand before voting down. Such a silly thing this voting down anyway. It should not reduce reputation.

Control name from Variable or Dataset. (Combobox)(.items.add)(.datasource)

I've checked for hours but I can't seem to find anything to help.
I want to loop through tables and columns from a dataset and use the column name in a combobox.items.add() line, however the eventual goal is to fill the combobox from the dataset itself possibly in a combobox.datasource line.
The first problem is that I can't get the code correct to setup the combobox control where it allows me to use .items.add("") and in extension .datasource
Error Message = "Object reference not set to an instance of an object"
dstcopt is the dataset from a oledbDataAdapter .fill(dstcopt,"table") line (which returns correct values)
tc_opt is a tab name on a tab control where the comboboxes are
For Each dstable In dstcopt.Tables
For Each dscolumn In dstable.Columns
Dim colName As String = dscolumn.ToString
MsgBox(colName) 'This retuns "aantigen"
Dim cb As ComboBox = Me.tc_opt.Controls("cb_" & colName)
cb.Items.Add(colName)
'cb_aantigen.DataSource = dstcopt.Tables(dstable.ToString)
'cb_aantigen.DisplayMember = "aantigen"
'cb_atarget.DataSource = dstcopt.Tables(dstable.ToString)
'cb_atarget.DisplayMember = "atarget"
Next
Next
The second problem comes when I do it manually (which works) using the exact combobox names cb_aantigen and cb_atarget as seen in the comments.
The problem is that once the form is loaded and the cb's are filled with the correct values, I can't change the value in any single cb individually, when I change one value it changes them all (there is 15 comboboxes in total) I know this is down to using a dataset, but I don't know away to 'unlink them from each other or the dataset'
Not sure if I need to split this into 2 questions, but help on either problem would be appreciated.
EDIT:
After looking at only this section of code for a day. This is what I have come up with to tackle both the problems at once.
The combobox control not working was down to using a tab tc_opt instead of a groupbox gp_anti
The issue with splitting the dataset up into individual comboboxes, I've worked around by taking the value of each cell in the database and adding it separately, probably a better way to do it though
For Each dstable As DataTable In dstcopt.Tables
For Each dscolumn As DataColumn In dstable.Columns
Dim colName As String = dscolumn.ToString
Dim cb(2) As ComboBox
cb(0) = CType(Me.gp_anti.Controls("cb_" & colName), ComboBox)
cb(1) = CType(Me.gp_rec.Controls("cb_" & colName), ComboBox)
cb(2) = CType(Me.gp_nat.Controls("cb_" & colName), ComboBox)
For icb = 0 To cb.Count - 1
If Not (IsNothing(cb(icb))) Then
For irow = 0 To dstable.Rows.Count - 1
If dstable.Rows(irow)(colName).ToString <> Nothing Then
Dim icbitemdupe As Boolean = False
If cb(icb).Items.Contains(dstable.Rows(irow)(colName).ToString) Then
icbitemdupe = True
End If
If icbitemdupe = False Then
cb(icb).Items.Add(dstable.Rows(irow)(colName).ToString)
End If
End If
Next
End If
Next
Next
Next

VB 2008 Transferring stored values to textbox after initial textbox value is cleared

Self teaching VB beginner here.
I have a data entry section that includes...
2 comboboxes(cbx_TruckType, cbx_DoorNumber)
-------cbx_TruckType having 2 options (Inbound, Outbound)
-------cbx_DoorNumber having 3 options (Door 1, Door 2, Door 3)
2 textboxes (txb_CustomerName, txb_OrderNumber)
-------txb_CustomerName will hold a customer name
-------txb_OrderNumber will hold an order number
and finally...
a button(btn_EnterTruck) that transfers the text from the comboxes and textboxes to the following...
2 Tabs
The 1st tab has
2 buttons(btn_Door1, btn_Door2)
btn_Door1 has 3 corresponding textboxes
-------txb_TruckTypeDoor1, txb_CustomerNameDoor1, txb_OrderNumberDoor1
btn_Door2 has 3 corresponding textboxes
-------txb_TruckTypeDoor2, txb_CustomerNameDoor2, txb_OrderNumberDoor2
The 2nd tab has
1 button(btn_Door3)
btn_Door1 has 3 corresponding textboxes
-------txb_TruckTypeDoor3, txb_CustomerNameDoor3, txb_OrderNumberDoor3
Currently, I have code (that works thanks to another question I had!) that, upon btn_EnterTruck.click, will transfer the text to the corresponding textboxes.
Here's my problem...
I've coded a msgbox to pop-up (when Inbound is selected from the cbx_TruckType) asking if there is an Outbound. If I click "Yes", an inputbox pops-up and asks for an order number. The button then transfers the Inbound information to the textboxes and stores the Outbound order number.
When I click btn_Door1(or 2 or 3), it clears the text from its corresponding textboxes. (Using me.controls)
( I would add code for all of the above, but I figure its a moot point, because it works)
What I want to happen...
I want to have the stored Outbound number to be saved with a reference to which door number it corresponds to. Then upon btn_DoorX click, it will fill that order number into the corresponding textbox. I don't need the text stored/saved when the app is closed.
And I have no idea how to do that.
*After some tooling, I've done the following, but it does not work"
I declared these at the class level.
Dim str_SameTruckPODoor1, str_SameTruckPODoor2, str_SameTruckPODoor3 As String
This code is in the btn_EnterTruck event
Dim str_ErrOutDoorName As String = cbx_DoorNumber.Text
Dim str_OutboundDoorName As String = str_ErrOutDoorName.Replace(" ", "")
Dim ArrayForPONumbers As Control() = Me.Controls.Find("str_SameTruckPO" & str_OutboundDoorName, True)
If cbx_TruckType.Text = "Inbound" Then
Dim OutboundMsg = "Is there an Outbound with this truck information?"
Dim Title = "Outbound?"
Dim style = MsgBoxStyle.YesNo Or MsgBoxStyle.DefaultButton2 Or _
MsgBoxStyle.Question
Dim response = MsgBox(OutboundMsg, style, Title)
If response = MsgBoxResult.Yes Then
Dim NeedPOMessage, NeedPOTitle, defaultValue As String
Dim PONumberOutbound As String
' Set prompt.
NeedPOMessage = "Enter the PO Number"
' Set title.
NeedPOTitle = "PO# For Outbound"
defaultValue = "?" ' Set default value.
' Display message, title, and default value.
PONumberOutbound = InputBox(NeedPOMessage, NeedPOTitle, defaultValue)
' If user has clicked Cancel, set myValue to defaultValue
If PONumberOutbound Is "" Then PONumberOutbound = defaultValue
ArrayForPONumbers(0) = PONumberOutbound
End If
End If
I'm getting an error message on
ArrayForPONumbers(0) = PONumberOutbound ' Cannot convert string to .controls
And I have the following code in the btn_Door1 event - it handles btn_Door2, btn_Door3
Dim WhichButton As Button = CType(sender, Button)
Dim str_ErrDoorName As String = WhichButton.Name
Dim str_DoorName As String = str_ErrDoorName.Replace("btn_", "")
Dim str_DoorType As Control() = Me.Controls.Find("txb_" & str_DoorName & "Type", True)
Dim str_Customer As Control() = Me.Controls.Find("txb_" & str_DoorName & "Customer", True)
Dim str_OrderNumber As Control() = Me.Controls.Find("txb_" & str_DoorName & "OrderNumber", True)
Dim SecondArrayForPONumbers As Control() = Me.Controls.Find("str_SameTruckPO" & str_DoorName, True)
If str_DoorType(0).Text = "Outbound" Then
str_DoorType(0).Text = ""
str_Customer(0).Text = ""
str_OrderNumber(0).Text = ""
ElseIf SecondArrayForPONumbers(0).Text.Length > 0 Then
str_DoorType(0).Text = "Outbound"
str_OrderNumber(0).Text = Me.Controls("str_SameTruckPO" & str_DoorName).Text
End If
Any help is appreciated. If I'm not clear on what I'm asking or haven't given enough details, please let me know.
Edit: Added info based on comment, Added code, Changed Title
How long do you want this data to be stored? IE: longer than the life of the open application? If the application is closed is it alright if the data is lost? If not, you may want to consider writing this data to an external database.

Listview help needed

I am confused being a relatively new user to vb.net. Why my listview is not amending the value in the list? If I may, so I have a correct working of how listview displays its data from database. I have a general question in addition to my code problem.
I have five columns in my listview (0-4). Am I correct in saying that if my access database contained say 10 fields but I only needed to display five of them but one of them was field (9), then would code the list like my code below, which is not changing the value and will only display the list if I remove the 'else' statement.
What is the error? Many thanks
UPDATED CODE:
oledbCnn.ConnectionString = My.Settings.storageConnectionString
oledbCnn.Open()
'drcount = Convert.ToInt32(dr("RowCount"))
sql = "Select TOP 100 * from Requests ORDER BY [Date-time received] DESC"
Debug.Print(sql)
Dim oledbCmd As OleDbCommand = New OleDbCommand(sql, oledbCnn)
Using dr = oledbCmd.ExecuteReader()
'clear items in the list before populating with new values
'lvRequests.Items.Clear()
While dr.Read()
If dr.HasRows Then
Dim LVI As New ListViewItem
With LVI
.Text = dr(0).ToString()
.UseItemStyleForSubItems = False
.SubItems.Add(CDate(dr(5)).ToShortDateString())
.SubItems.Add(dr(1).ToString())
.SubItems.Add(dr(3).ToString())
If dr(3).ToString = "D" Then
.SubItems(3).Text = "Destroyed"
ElseIf dr(3).ToString = "O" Then
.SubItems(3).Text = "Out"
ElseIf dr(3).ToString = "I" Then
.SubItems(3).Text = "Intake"
End If
.SubItems.Add(dr(9).ToString())
If dr(9).ToString = "DEMO" Then
.SubItems(9).Text = "Done"
End If
End With
lvRequests.Items.Add(LVI)
lvcount += 1
End If
End While
End Using
There is not enough info to be really sure what is going on. It appears that you pull 10 columns from the DB, but if you only post 5 of them to the LV, then there should only be 5 subitems. So this is wrong:
If dr(9).ToString() = "DEMO" Then
lvRequests.Items(lvRequests.Items.Count - 1).SubItems(9).Text = "Done"
' should probably be:
If dr(9).ToString() = "DEMO" Then
lvRequests.Items(lvRequests.Items.Count - 1).SubItems(4).Text = "Done"
What might make it clearer at least in code would be to use Names for the subitems. If you instance a SubItem object rather than use a default constructor, you can assign a name and reference them that way instead:
Dim si As New ListViewItem.ListViewSubItem
With si
.Text = dr(X).ToString ' dunno whats in there
' this is probably not exactly right, but give the SubItem
' the same name as the db column
.Name = dr.Table.Columns(X).ColumnName
End With
thisItem.SubItems.Add(si) ' add sub to Item collection
Now, your code can use the name rather than index:
If dr(9).ToString() = "DEMO" Then
lvReq.Items(lvReq.Items.Count - 1).SubItems("TheColumnName").Text = "Done"
it no longer really matters how many columns or subitems there are. The ListViewItem.SubItems collection does not require sub item names to be unique, so it is possible to end up with 2 with the same name, but if you map from the DR/DT/DB correctly, it should take care of itself.
If the LV is bound to the datasource (you did not say), then there could be as many SubItems as db/datasource columns (never actually used an LV that way).

Adding two column values to listbox in vb.net

I have a table named users which has the following columns in it
User_id,user_name,user_pwd,First_Name,Middle_Name,Last_Name and user_type.
I have dataset named dst and created a table called user in the dataset. Now I want to populate listbox with user_Name, First_Name, Last_name of each and every row in the table user.
I am able to add one column value at a time but not getting how to add multiple column values of each row to listbox
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(row("User_Name"))
Next
Above code works perfectly but I also want to add First_name as well as last_name to the list box at the same time.
Use same approach as you have, but put all values you want in one string.
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
Dim sItemTemp as String
sItemTemp = String.Format("{0},{1},{2}", row("User_Name"), row("First_Name"), row("Last_Name"))
lstUsers.Items.Add(sItemTemp)
Next
String.Format() function will call .ToString() on all parameters.
In this case if row(ColumnName) is NULL value then .ToString() return just empty string
You have 2 choices:
Using the ListBox:
To use the ListBox, set the font to one that is fixed width like courier new (so that the columns line up), and add the items like this:
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(RPAD(row("User_Name"),16) & RPAD(row("First_Name"),16) & RPAD(row("Last_Name"),16))
Next
The RPAD function is defined like this:
Function RPAD(a As Object, LENGTH As Object) As String
Dim X As Object
X = Len(a)
If (X >= LENGTH) Then
RPAD = a : Exit Function
End If
RPAD = a & Space(LENGTH - X)
End Function
Adjust the LENGTH argument as desired in your case. Add one more for at least one space. This solution is less than ideal because you have to hard-code the column widths.
Use a DataGridView control instead of a ListBox. This is really the best option, and if you need, you can even have it behave like a ListBox by setting the option to select the full row and setting CellBorderStyle to SingleHorizontal. Define the columns in the designer, but no need to set the widths - the columns can auto-size, and I set that option in the code below. if you still prefer to set the widths, comment out the AutoSizeColumnsMode line.
The code to set up the grid and add the rows goes like this:
g.Rows.Clear() ' some of the below options are also cleared, so we set them again
g.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.AllCells
g.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal
g.SelectionMode = DataGridViewSelectionMode.FullRowSelect
g.AllowUserToAddRows = False
g.AllowUserToDeleteRows = False
g.AllowUserToOrderColumns = True
For Each row As DataRow In dt.Rows
g.Rows.Add(row("User_Name"), row("First_Name"), row("Last_Name"))
Next
You might solved your problem by now but other users like me might have issue with it.
Above answers given worked for me even but I found a same answer in a simple way according to what I want..
cmd = New SqlCommand("select User_Name, First_Name, Last_Name from User")
Dim dr As SqlDataReader = cmd.ExecuteReader(YourConnectionString)
If dr.HasRows Then
Do While dr.Read
lst.Items.Add(dr.Item(0).ToString & " " & dr.Item(1).ToString & " " & dr.Item(2).ToString)
Loop
End If
This worked for me, maybe wrong way but I found it simple :)
May I suggest you use a ListView control instead of Listbox?
If you make the switch, here's a sample subroutine you could use to fill it up with the data you said you want. Adapt it the way you like; there's much room for improvement but you get the general idea:
Public Sub FillUserListView(lstUsers As ListView, Dst As DataSet)
Dim columnsWanted As List(Of String) = New List(Of String)({"User_Name", "First_Name", "Last_Name"})
Dim dt As DataTable = Dst.Tables("user")
Dim columns As Integer = 0
Dim totalColumns = 0
Dim rows As Integer = dt.Rows.Count
'Set the column titles
For Each column As DataColumn In dt.Columns
If columnsWanted.Contains(column.ColumnName) Then
lstUsers.Columns.Add(column.ColumnName)
columns = columns + 1
End If
totalColumns = totalColumns + 1
Next
Dim rowObjects(columns - 1) As ListViewItem
Dim actualColumn As Integer = 0
'Load up the rows of actual data into the ListView
For row = 0 To rows - 1
For column = 0 To totalColumns - 1
If columnsWanted.Contains(dt.Columns(column).ColumnName) Then
If actualColumn = 0 Then
rowObjects(row) = New ListViewItem()
rowObjects(row).SubItems(actualColumn).Text = dt.Rows(row).Item(actualColumn)
Else
rowObjects(row).SubItems.Add(dt.Rows(row).Item(actualColumn))
End If
lstUsers.Columns.Item(actualColumn).Width = -2 'Set auto-width
actualColumn = actualColumn + 1
End If
Next
lstUsers.Items.Add(rowObjects(row))
Next
lstUsers.View = View.Details 'Causes each item to appear on a separate line arranged in columns
End Sub