I'm trying to search one datatable for a string, so if new hits are appeared the action is triggered. How to do that?
My current code:
If searchvalue <> "" Then
foundRows = table.Select("Name LIKE '%" & searchvalue & "%'")
If foundRows.Length = 0 Then
'none found
Else
For Each r In foundRows
notif("Found "&r.itemarray(0) & " in " & r.itemarray(1))
Next
End If
End If
the "notif" function is called for every hit each time the sub is called; but i want it to be called once for every unique hit. How to do it?
Using case: say, first time sub is called when table is like that:
something foo
smthelse bar
the search string is "some", the Notif called once for "something foo". Next time the sub is called table is like that:
something foo
something else
smthelse bar
Now Notif should be called only for "something else"
I would suggest to use Linq-To-DataSet instead which makes your code more readable, maintainable and also has some nice features like grouping:
If searchvalue.Length <> 0 Then
Dim foundNamegroups = From row In table
Let Name = row.Field(Of String)("Name")
Where Name.Contains(searchvalue)
Group row By Name Into NameGroup = Group
If foundNamegroups.Any() Then
For Each grp In foundNamegroups
' note that the DataRows are in grp.NameGroup
Dim msg = String.Format("Found {0} rows for name {1}", grp.NameGroup.Count(), grp.Name)
notif(msg)
Next
End If
End If
Found the solution - i used the row.RowState property.
Each time the row is changed or added, its row.RowState property equals either DataRowState.Added or DataRowState.Modified, and when the row.AcceptChanges() called it becomes DataRowState.Unchanged .
Related
I am trying to use this code from this answer but I keep getting this error
'Item' is not a member of 'DataRow()'
Does anyone know why? Or how I can get the first row of a data table?
Dim results As DataRow() = Students.Select("ID=1 and FirstName='Karthik'", "ID")
Test1Highest.Text = results.Item("Name") & " Got the highest in test 1!"
From DataTable.Select Method, we can see that the results variable will be an Array of DataRow objects.
Therefore, to access the first item in the list, you will need to add an Array Indexer.
Change this line:
Test1Highest.Text = results.Item("Name") & " Got the highest in test 1!
to be
If results IsNot Nothing AndAlso results.Count > 0 Then
Test1Highest.Text = results(0).Item("Name") & " Got the highest in test 1!
Else
Test1Highest.Text = "No results!"
End If
Or, you can do (using FirstOrDefault())
Dim singleResult As DataRow = Students.Select("ID=1 and FirstName='Karthik'", "ID").FirstOrDefault()
If singleResult IsNot Nothing Then
Test1Highest.Text = singleResult.Item("Name") & " Got the highest in test 1!
Else
Test1Highest.Text = "No results!"
End If
Looking at the question you linked to, the accepted answer has the command FirstOrDefault() being called from the result of the Select statement. This, like the name suggests, will return the first item in the array or a Null value if there are no elements in the array.
I have a Part class with the fields list in the code below. I have a DataGridView control, which I am filtering with the Advanced DGV (ADGV) DLL from NUGET. I must include the ADGV in my winform. I currently have a DataGridView, a search box on the form, and a button to run the following function. I need to go through all of the visible rows, collect a unique list of part numbers with their most recent revisions, and then color the rows in DataGridView which are out of date by checking the part number and rev on each row against the mostuptodate list. For 45,000 entries displayed in DataGridView, this take ~17 secs. For ~50 entries, it take ~1.2 seconds. This is extremely inefficient, but I can't see a way to cut the time down.
Sub highlightOutdatedParts()
'Purpose: use the results in the datagridview control, find the most recent revision of each part, and
' highlight all outdated parts relative to their respective most recent revisions
'SORT BY PART NUMBER AND THEN BY REV
If resultsGrid.ColumnCount = 0 Or resultsGrid.RowCount = 0 Then Exit Sub
Dim stopwatch As New Stopwatch
stopwatch.Start()
resultsGrid.Sort(resultsGrid.Columns("PartNumber"), ListSortDirection.Ascending)
Dim iBag As New ConcurrentBag(Of Part)
Dim sortedList As Generic.List(Of Part)
For Each row As DataGridViewRow In resultsGrid.Rows
If row.Visible = True Then
Dim iPart As New Part()
Try
iPart.Row = row.Cells(0).Value
iPart.Workbook = CStr(row.Cells(1).Value)
iPart.Worksheet = CStr(row.Cells(2).Value)
iPart.Product = CStr(row.Cells(3).Value)
iPart.PartNumber = CStr(row.Cells(4).Value)
iPart.ItemNo = CStr(row.Cells(5).Value)
iPart.Rev = CStr(row.Cells(6).Value)
iPart.Description = CStr(row.Cells(7).Value)
iPart.Units = CStr(row.Cells(8).Value)
iPart.Type = CStr(row.Cells(9).Value)
iPart.PurchCtgy = CStr(row.Cells(10).Value)
iPart.Qty = CDbl(row.Cells(11).Value)
iPart.TtlPerProd = CDbl(row.Cells(12).Value)
iPart.Hierarchy = CStr(row.Cells(13).Value)
iBag.Add(iPart)
Catch ice As InvalidCastException
Catch nre As NullReferenceException
End Try
End If
Next
sortedList = (From c In iBag Order By c.PartNumber, c.Rev).ToList() ' sort and convert to list
Dim mostUTDRevList As New Generic.List(Of Part) ' list of most up to date parts, by Rev letter
For sl As Integer = sortedList.Count - 1 To 0 Step -1 'start at end of list and work to beginning
Dim query = From entry In mostUTDRevList ' check if part number already exists in most up to date list
Where entry.PartNumber = sortedList(sl).PartNumber
Select entry
If query.Count = 0 Then ' if this part does not already exist in the list, add.
mostUTDRevList.Add(sortedList(sl))
End If
Next
'HIGHLIGHT DATAGRIDVIEW ROWS WHERE PART NUMBERS ARE OUT OF DATE
For Each row As DataGridViewRow In resultsGrid.Rows
' if that part with that Rev does not exist in the list, it must be out of date
Try
Dim rowPN As String = CStr(row.Cells(4).Value).ToUpper ' get part number
Dim rowR As String = CStr(row.Cells(6).Value).ToUpper ' get Rev
Dim query = From entry In mostUTDRevList ' check if that part number with that Rev is in the list.
Where entry.PartNumber.ToUpper.Equals(rowPN) AndAlso
entry.Rev.ToUpper.Equals(rowR)
Select entry
If query.Count = 0 Then ' if the part is out of date highlight its' row
row.DefaultCellStyle.BackColor = Color.Chocolate
End If
Catch ex As NullReferenceException
Catch ice As InvalidCastException
End Try
Next
resultsGrid.Select()
stopwatch.Stop()
If Not BackgroundWorker1.IsBusy() Then timertextbox.Text = stopwatch.Elapsed.TotalSeconds.ToString & " secs"
MessageBox.Show("Highlighting completed successfully.")
End Sub
It is almost always faster to work with the data than the control. The control is simply the means to present a view of the data (in a grid) to the users. Working with the data from there requires too much converting to be effieicent. Then, use the DGV events to highlight the rows
Its hard to tell all the details of what you are doing, but it looks like you are comparing the data to itself (as opposed to some concrete table where the lastest revision codes are defined). Nor is it clear why the datasources are collections, ConcurrentBags etc. The key would be to use collections optimized for the job.
To demonstrate, I have a table with 75,000 rows; the product codes are randomly selected from a pool of 25,000 and a revision code is a random integer (1-9). After the DGV datasource is built (a DataTable) a LookUp is created from the ProductCode-Revision pair. This is done once and once only:
' form level declaration
Private PRCodes As ILookup(Of String, Int32)
' go thru table
' group by the product code
' create an anon Name-Value object for each,
' storing the code and highest rev number
' convert result to a LookUp
PRCodes = dtSample.AsEnumerable.
GroupBy(Function(g) g.Item("ProductCode"),
Function(key, values) New With {.Name = key.ToString(), .Value = values.
Max(Of Int32)(Function(j) j.Field(Of Int32)("RevCode"))
}).
ToLookup(Of String, Int32)(Function(k) k.Name, Function(v) v.Value)
Elapsed time via stopwatch: 81 milliseconds to create the collection of 23731 items. The code uses an anonymous type to store a Max Revision code for each product code. A concrete class could also be used. If you're worried about mixed casing, use .ToLowerInvariant() when creating the LookUp (not ToUpper -- see What's Wrong With Turkey?) and again later when looking up the max rev.
Then rather than looping thru the DGV rows use the RowPrePaint event:
If e.RowIndex = -1 Then Return
If dgv1.Rows(e.RowIndex).IsNewRow Then Return
' .ToLowerInvariant() if the casing can vary row to row
Dim pc = dgv1.Rows(e.RowIndex).Cells("ProductCode").Value.ToString()
Dim rv = Convert.ToInt32(dgv1.Rows(e.RowIndex).Cells("RevCode").Value)
Dim item = PRCodes(pc)(0)
If item > rv Then
dgv1.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.MistyRose
End If
Notes
It takes some time to create the DataSource, but 75,000 rows is a lot to throw at a user
The time to create the LookUp is minimal - barely measurable
There is no noticeable wait in displaying them because a) the LookUp is made for this sort of thing, b) rows are done as needed when they are displayed. Row # 19,999 may never be processed if the user never scrolls that far.
This is all geared to just color a row. If you needed to save the Current/NotCurrent state for each row, add a Boolean column to the DataTable and loop on that. The column can be invisible if to hide it from the user.
The random data results in 47,000 out of date RevCodes. Processing 75k rows in the DataTable to set the flag takes 591 milliseconds. You would want to do this before you set the DataTable as the DataSource to prevent changes to the data resulting in various events in the control.
In general, the time to harvest the max RevCode flag and even tag the out of date rows is a trivial increment to creating the datasource.
The Result:
The data view is sorted by ProductCode so that the coloring of lower RevCodes is apparent.
We surely cant grok all the details and constraints of the system from a small snippet - even the data types and original datasource are a guess for us. However, this should provide some help with better look-up methods, and the concept of working with the data rather than the user's view.
One thing is the revision code - yours is treating them as a string. If this is alphanumeric, it may well not compare correctly - "9" sorts/compares higher than "834" or "1JW".
See also:
Lookup(Of TKey, TElement) Class
Anonymous Types
The solution was spurred in part by #Plutonix.
Sub highlightOutdatedParts()
If resultsGrid.ColumnCount = 0 Or resultsGrid.RowCount = 0 Then Exit Sub
Dim stopwatch As New Stopwatch
stopwatch.Start()
resultsGrid.DataSource.DefaultView.Sort = "PartNumber ASC, Rev DESC"
resultsGrid.Update()
'HIGHLIGHT DATAGRIDVIEW ROWS WHERE PART NUMBERS ARE OUT OF DATE
Dim irow As Long = 0
Do While irow <= resultsGrid.RowCount - 2
' if that part with that Rev does not exist in the list, it must be out of date
Dim utdPN As String = resultsGrid.Rows(irow).Cells(4).Value.ToString().ToUpper()
Dim utdRev As String = resultsGrid.Rows(irow).Cells(6).Value.ToString().ToUpper()
Dim iirow As Long = irow + 1
'If iirow > resultsGrid.RowCount - 1 Then Exit Do
Dim activePN As String = Nothing
Dim activeRev As String = Nothing
Try
activePN = resultsGrid.Rows(iirow).Cells(4).Value.ToString().ToUpper()
activeRev = resultsGrid.Rows(iirow).Cells(6).Value.ToString().ToUpper()
Catch ex As NullReferenceException
End Try
Do While activePN = utdPN
If iirow > resultsGrid.RowCount - 1 Then Exit Do
If activeRev <> utdRev Then
resultsGrid.Rows(iirow).DefaultCellStyle.BackColor = Color.Chocolate
End If
iirow += 1
Try
activePN = resultsGrid.Rows(iirow).Cells(4).Value.ToString().ToUpper()
activeRev = resultsGrid.Rows(iirow).Cells(6).Value.ToString().ToUpper()
Catch nre As NullReferenceException
Catch aoore As ArgumentOutOfRangeException
End Try
Loop
irow = iirow
Loop
resultsGrid.Select()
stopwatch.Stop()
If Not BackgroundWorker1.IsBusy() Then
timertextbox.Text = stopwatch.Elapsed.TotalSeconds.ToString & " secs"
resultcounttextbox.Text = resultsGrid.RowCount - 1 & " results"
End If
MessageBox.Show("Highlighting completed successfully.")
End Sub
How can i check for a character after other text within a listbox?
e.g
Listbox contents:
Key1: V
Key2: F
Key3: S
Key4: H
How do I find what comes after Key1-4:?
Key1-4 will always be the same however what comes after that will be user defined.
I figured out how to save checkboxes as theres only 2 values to choose from, although user defined textboxes is what im struggling with. (I have searched for solutions but none seemed to work for me)
Usage:
Form1_Load
If ListBox1.Items.Contains("Key1: " & UsersKey) Then
TextBox1.Text = UsersKey
End If
Which textbox1.text would then contain V / whatever the user defined.
I did try something that kind of worked:
Form1_Load
Dim UsersKey as string = "V"
If ListBox1.Items.Contains("Key1: " & UsersKey) Then
TextBox1.Text = UsersKey
End If
but i'm not sure how to add additional letters / numbers to "V", then output that specific number/letter to the textbox. (I have special characters blocked)
Reasoning I need this is because I have created a custom save settings which saves on exit and loads with form1 as the built in save settings doesn't have much customization.
e.g Can't choose save path, when filename is changed a new user.config is generated along with old settings lost.
Look at regular expressions for this.
Using the keys from your sample:
Dim keys As String = "VFSH"
Dim exp As New RegEx("Key[1-4]: ([" & keys& "])")
For Each item As String in ListBox1.Items
Dim result = exp.Match(item)
If result.Success Then
TextBox1.Text = result.Groups(1).Value
End If
Next
It's not clear to me how your ListBoxes work. If you might find, for example, "Key 2:" inside ListBox1 that you need to ignore, you will want to change the [1-4] part of the expression to be more specific.
Additionally, if you're just trying to exclude unicode or punctuation, you could also go with ranges:
Dim keys As String = "A-Za-z0-9"
If you are supporting a broader set of characters, there are some you must be careful with: ], \, ^, and - can all have special meanings inside of a regular expression character class.
You have multiple keys, I assume you have multiple textboxes to display the results?
Then something like this would work. Loop thru the total number of keys, inside that you loop thru the alphabet. When you find a match, output to the correct textbox:
Dim UsersKey As String
For i As Integer = 1 To 4
For Each c In "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
UsersKey = c
If ListBox1.Items.Contains("Key" & i & ": " & UsersKey) Then
Select Case i
Case 1
TextBox1.Text = UsersKey
Case 2
TextBox2.Text = UsersKey
Case 3
TextBox3.Text = UsersKey
Case 4
TextBox4.Text = UsersKey
End Select
Exit For 'match found so exit inner loop
End If
Next
Next
Also, you say your settings are lost when the filename is changed. I assume when the version changes? The Settings has an upgrade method to read from a previous version. If you add an UpgradeSettings boolean option and set it to True and then do this at the start of your app, it will load the settings from a previous version:
If My.Settings.UpgradeSettings = True Then
My.Settings.Upgrade()
My.Settings.Reload()
My.Settings.UpgradeSettings = False
My.Settings.Save()
End If
Updated Answer:
Instead of using a listtbox, read the settings file line by line and output the results to the correct textbox based on the key...something like this:
Dim settingsFile As String = "C:\settings.txt"
If IO.File.Exists(settingsFile) Then
For Each line As String In IO.File.ReadLines(settingsFile)
Dim params() As String = Split(line, ":")
If params.Length = 2 Then
params(0) = params(0).Trim
params(1) = params(1).Trim
Select Case params(0)
Case "Key1"
Textbox1.Text = params(1)
Case "Key2"
Textbox2.Text = params(1)
End Select
End If
Next line
End If
You can associate text box with a key via its Name or Tag property. Lets say you use Name. In this case TextBox2 is associated with key2. TextBox[N] <-> Key[N]
Using this principle the code will look like this [considering that your list item is string]
Sub Test()
If ListBox1.SelectedIndex = -1 Then Return
Dim data[] As String = DirectCast(ListBox1.SelectedItem, string).Split(new char(){":"})
Dim key As String = data(0).Substring(3)
Dim val As String = data(1).Trim()
' you can use one of the known techniques to get control on which your texbox sits.
' I omit this step and assume "Surface1" being a control on which your text boxes sit
DirectCast(
(From ctrl In Surface1.Controls
Where ctrl.Name = "TextBox" & key
Select ctrl).First()), TextBox).Text = val
End Sub
As you can see, using principle I just explained, you have little parsing and what is important, there is no growing Select case if, lets say, you get 20 text boxes. You can add as many text boxes and as many corresponding list items as you wish, the code need not change.
I am looking to find something in Visual Basic that basically states that if something collides with something with a certain class, it executes code. I may not be using correct terms, so when I say object I mean like a label or picture box, and a class is... well like a class in HTML, I guess, like an object with a trait.
The pseudocode would look something like this:
If object.Bounds.IntersectsWith([object with certain class]) Then execute code
Otherwise, the game's 'if' statements will overwhelm... Also I am new to Visual Basic language, so please keep it as simple as possible.
Here is what I have already:
If carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 1 Then
directiona = 0
carblue.Top += 2
ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 2 Then
directiona = 0
carblue.Left += 2
ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 3 Then
directiona = 0
carblue.Top -= 2
ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 4 Then
directiona = 0
carblue.Left -= 2
End If
Where carblue is the object being controlled, boundary1 is the obstacle that stops the car from moving (on collision) and directiona is the value of the direction the car is travelling (1 is up, 2 is left, etc).
(Moved from S.A. Programmers site)
Without actual sample code to work with, it's not easy to provide a specific solution. I don't know how many controls you have moving around, is it 2? 10? 10,000? Assuming you have 10+ controls moving around, this is how I would handle it.
I would use a datatable to keep a record of the Bounds for each Control that moves or is collidable. After a control moves, update that row in the datatable, look for collisions, then check the object types to determine what kind of class the collided object is, and then run the code as needed.
Public MovingControls As DataTable
Sub Main()
'Build the DataTable
MovingControls = New DataTable("ControlBounds")
MovingControls.Columns.Add("Name", GetType(String))
MovingControls.Columns.Add("x1", GetType(Integer))
MovingControls.Columns.Add("x2", GetType(Integer))
MovingControls.Columns.Add("y1", GetType(Integer))
MovingControls.Columns.Add("y2", GetType(Integer))
End Sub
'Call this only when a control/object is created
Sub MovingControlAdded(sender As Control)
Dim Row As DataRow = MovingControls.NewRow
Row("Name") = sender.Name
Dim BoundsRect As Drawing.Rectangle = sender.Bounds
Row("x1") = sender.Bounds.Left
Row("x2") = sender.Bounds.Right
Row("y1") = sender.Bounds.Bottom
Row("y2") = sender.Bounds.Top
MovingControls.Rows.Add(Row)
End Sub
'Call this only when a control/object has moved
Sub MovingControlMoved(sender As Control)
'Update the location of this Control
Dim Row() As DataRow = MovingControls.Select("Name = '" & sender.Name & "'")
'Select returns an array of Rows but there should only be 1 row for each Control
Row(0)("x1") = sender.Bounds.Left
Row(0)("x2") = sender.Bounds.Right
Row(0)("y1") = sender.Bounds.Bottom
Row(0)("y2") = sender.Bounds.Top
'Collision check
Dim CollidedRows() As DataRow = MovingControls.Select("(" & sender.Bounds.Right & " >= x1)" &
"AND (" & sender.Bounds.Left & " <= x2)" &
"AND (" & sender.Bounds.Bottom & " <= y2)" &
"AND (" & sender.Bounds.Top & " >= y1)" &
"AND (Name <> '" & sender.Name & "'")
'Determine the object type and execute necessary code
For Each CollidedRow As DataRow In CollidedRows
Dim CollidedControl As Control = Me.Controls.Item(CollidedRow("Name"))
If CollidedControl.GetType = GetType(Label) Then
'Do stuff for labels
ElseIf CollidedControl.GetType = GetType(Button) Then
'Do stuff for buttons
End If
Next
End Sub
Caveat: This assumes 1 control is moving at a time. If Control A moves into Control B but Control B moves away at the same time, this code will still call a collision even though the collision was avoided. If you have multiple controls moving, you may want to split the MovingControlMoved method into 2 methods, one for updating the table and one for collision checks. Handle all movement first, then handle all collisions.
Depending on the complexity, you may want to create custom classes for collidable controls that inherit an interface for collisions. You can use System.Reflection to call RunMeOnCollision. This would eliminate the list of If statements.
Interface iCollidableBase
Sub RunMeOnCollision()
End Interface
Public Class CollidableLabel
Inherits Label
Implements iCollidableBase
Public Sub RunMeOnCollision() Implements iCollidableBase.RunMeOnCollision
Me.Text = "I have been collided"
End Sub
End Class
Public Class CollidableButton
Inherits Button
Implements iCollidableBase
Public Sub RunMeOnCollision() Implements iCollidableBase.RunMeOnCollision
Me.Text = "Ouch, that collision hurt!"
End Sub
End Class
Again, not knowing the full context here, I can't test my solution against your code. If you can post some additional details, I might be able to help more.
-E
I found what I needed from my programming teacher, using arrays.
In the public sub:
Dim walls(17) As PictureBox
Where 17 is the number of (In this case) boundaries that your form has. Also change PictureBox to the object you are using (for example labels).
Then in your form load:
For i = 1 To 17
walls(i) = Me.Controls("boundary" & i)
Next
I'm honestly not 100% sure about this, but the "boundary" string is a section of the name of my PictureBoxes, that are acting as boundaries. There names are boundary1, boundary2, etc. So you might change "boundary" to what your object's names are.
Next, when you want to check for something using the boundaries, declare
For i = 1 To 17
Then when you want to close checking for it,
Next
For the checking of collisions, use this:
If object.Bounds.IntersectsWith(walls(i).Bounds) Then
So in this case, the If statement would go between the For and Next lines.
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