List (Of T) as DataGridView.DataSource makes sorting fail - vb.net

I have read some threads about this "error" but I can't figure out how to solve my problem.
I have a class that looks something like this:
Public Class Person
Public Property Name As String
Public Property PhoneNumber As string
Public Property Age As Integer
Public sub New(ByVal Values As String())
Me.Name = Values(0)
Me.PhoneNumber = Values(1)
Me.Age = Convert.ToInt32(Values(2))
End Sub
End Class
I get my data from a semicolon separated file, and i create a list of Person objects by looping this file and split on semicolon. Like this
Dim PersonsList As New List(Of Person)
For Each line in textfile..........
PersonsList.Add(New Person(line.Split(";")))
Next
When the list is complete, I tell my DataGridView that DataSource is PersonsList.
This works like a charm, but I'm not able to sort the columns.
I found this post amongst many (where the class values are not properties, which mine are) and tried that converting function which did'nt really work in my case. The right amount of rows were created, but all of the columns were blank.
What am I missing?

If you use a datatable as the data source, column sorting is automatically enabled and you can sort the data by any column:
Dim dt As New DataTable
dt.Columns.AddRange(
{
New DataColumn("Name"),
New DataColumn("Phone"),
New DataColumn("Age")
})
For Each s As String In IO.File.ReadAllLines("textfile1.txt")
Dim temprow As DataRow = dt.NewRow
temprow.ItemArray = s.Split(";"c)
dt.Rows.Add(temprow)
Next
DataGridView1.DataSource = dt

Related

Retrieve list that is saved in a datatable

I created a datatable containing the list of notes for songs:
Private Table As New DataTable
Public Sub New()
With Table
.Columns.Add("Name")
.Columns.Add("NoteList")
.Rows.Add("GOT", GOT)
.Rows.Add("Yesterday", Yesterday)
End With
End Sub
GOT and Yesterday are lists of notes (notes is a class containing note, duration etc..)
On the form I then assign the datatable to a combobox:
ComboSongs.DisplayMember = Songs.DataTable.Columns(0).ColumnName
ComboSongs.ValueMember = Songs.DataTable.Columns(1).ColumnName
ComboSongs.DataSource = Songs.DataTable
I try to get the list of notes like this:
Dim songToPlay As List(Of Note) = CType(ComboSongs.SelectedValue, List(Of Note))
When I try to get the list I get the error:
System.InvalidCastException: 'Unable to cast object of type 'System.String' to type 'System.Collections.Generic.List`1[test.Note]'.'
Now I am unsure where I am getting it wrong. What would be the correct way to do this?
Your ValueMember is what is returned through the ComboBox.SelectedValue. So since you set the ValueMember like this
ComboSongs.ValueMember = Songs.DataTable.Columns(1).ColumnName
you only get the ColumnName. I assume that's a string and, well, the error message tells you it is one
... Unable to cast object of type 'System.String' ...
I guess that should be "NoteList", since that would be returned by Songs.DataTable.Columns(1).ColumnName
But this all doesn't make much sense, as I guess you are selecting a song there, either "Yesterday" or "GOT". At the point you're at it's so convoluted to return the DataTable rows, and index them. You will need to find the row by name and that is just too complicated when you could just create a class with strong names. I'll give you a class based solution but I'm not sure if you can make that change.
Private Class Song
Public Property Name As String
Public Property NoteList As List(Of Note)
End Class
Private Class Note
' your implementation
End Class
Dim songs As New List(Of Song)()
songs.Add(New Song() With {.Name = "GOT", .NoteList = New List(Of Note)})
songs.Add(New Song() With {.Name = "Yesterday", .NoteList = New List(Of Note)})
' need to populate those NoteLists first
ComboSongs.DisplayMember = "Name"
ComboSongs.DataSource = songs
Dim songToPlay = songs.SingleOrDefault(Function(s) s.Name = ComboSongs.SelectedValue)
Dim noteList = songToPlay.NoteList

extract list of string from list of custom class

i have a list(of custom class)
and i want to extract a list of all 'name' String, from it, through linq
I know how to do with a loop, but i need to get it with a linear, brief linq instruction.
i've checked this help
C# Extract list of fields from list of class
but i have problem in linq correct syntax
in particular because i would like to extract a New List(Of String)
Class Student
Sub New(ByVal NewName As String, ByVal NewAge As Integer)
Name = NewName
Age = NewAge
End Sub
Public Name As String
Public Age As Integer
End Class
Public Sub Main
Dim ClassRoom as New List(Of Student) From {New Student("Foo",33), New Student("Foo2",33), New Student("Foo3",22)}
Dim OneStudent as Student = ClassRoom(0)
Dim AllStudentsNames As New List(Of String) From {ClassRoom.Select(Function(x) x.Name <> OneStudent.Name).ToList}
End Sub
But something wrong...
Any help?
P.S. Since c# it's close to vb.Net, also c# helps are well welcome.
First, you don't need to create a new list From the one returned by the LINQ method. It's already in a new list at that point, so you can just set AllStudentsNames equal directly to what the ToList method returns.
Second, you are not selecting the name. You are selecting the result of the equality test to see if the names are different. In other words, when you say Select(Function(x) x.Name <> OneStudent.Name), that returns a list of booleans, where they true if the names are different and false if the names are the same. That's not what you want. You want the list of names, so you need to select the name.
Third, if you need to filter the list so that it only returns ones where the name is different, then you need to add a call to the Where method.
Dim AllStudentsNames As List(Of String) = ClassRoom.
Where(Function(x) x.Name <> OneStudent.Name).
Select(Function(x) x.Name).
ToList()

Populate combobox with a class - data from a sql query

Iam frustrated to accomplish a simply population of a combobox, below I have added one new item to the combobox everything seems to be fine.
Question 1 : But how could I get there the information's from the sql query, without having to add it all manually. [ I suppose by simply adding Items.Add line to the while loop ], but here is another thing - The start data is a database record previewer, So it is Simple Name Simple Surname [/] with a dropdown menu with all customers,
Question 2. The data I get from the mysql result is id,name,surname how to point it as the current displayed name/surname and for later purposes - like a update get the selected id of another customer from the dropdown? I don't need the insert command or code just need the information how can I get the id from a selection. If something is unclear don't hesitate to ask.
'Select the first item ( the selection would be a ID of the customer which isn't the index at all)
ComboBoxEdit.SelectedIndex = 0
Form
Dim properties As DevExpress.XtraEditors.Repository.RepositoryItemComboBox = _
ComboBoxEdit.Properties
properties.Items.Add(New Customers(1, "Ta", "t").ToString)
'Select the first item ( the selection would be a ID of the customer which isn't the index at all)
ComboBoxEdit.SelectedIndex = 0
Getting customers into Class Customers ( I guess its that way I need to do it )
Public Function init_customers()
' Create a list of strings.
Dim sql As String
Dim myReader As MySqlDataReader
con.Open()
sql = "select * from customers"
'bind the connection and query
With cmd
.Connection = con
.CommandText = sql
End With
myReader = cmd.ExecuteReader()
While myReader.Read()
list.Add(New Customers(myReader.GetInt64(0), myReader.GetString(1), myReader.GetString(2)))
End While
con.Close()
'Return list
End Function
The class customers
Public Class Customers
Public Sub New(ByVal id As Integer, ByVal name As String, ByVal surname As String)
Me.ID = id
Me.Imie = name
Me.Nazwisko = surname
End Sub
#Region "Get/Set"
Public Property ID() As Integer
Get
Return Me._id
End Get
Set(ByVal value As Integer)
Me._id = value
End Set
End Property
Public Property Imie() As String
Get
Return Me._imie
End Get
Set(ByVal value As String)
Me._imie = value
End Set
End Property
Public Property Nazwisko() As String
Get
Return Me._nazwisko
End Get
Set(ByVal value As String)
Me._nazwisko = value
End Set
End Property
Public ReadOnly Property Surname() As Decimal
Get
Return Me._nazwisko
End Get
End Property
Public Overrides Function ToString() As String
Return _imie + " " + _nazwisko
End Function
#End Region
Private _id As Integer
Private _imie As String
Private _nazwisko As String
End Class
=========== Edit 2 =====================
Ok my dropdown is populated
As I said this is a record preview form so how can I get now the default selection of the combobox.
The thing is I pass there a string
Form1.GridView1.GetRowCellValue(Form1.GridView1.FocusedRowHandle, "Wystawione_na").ToString()
This code returns me SimpleName SimpleSurname - as a one string
Same method is applied to combobox display.
How can I get now the Id of the item, it has to somehow compared and returning a id so it could be set cmbx.SelectedIndex = 0 as the id of customer selection
I take a simpler route, not sure if it's the most efficient though:
Dim Conn As New SqlConnection
Conn.ConnectionString = sYourConnectionString
Conn.Open()
Dim da As New SqlDataAdapter("select * from customers", Conn)
Dim ds As New DataSet
da.Fill(ds, sSql)
cmbxCustomers.DataSource = ds.Tables(0)
cmbxCustomers.ValueMember = "ID" 'or whatever column you want
Of course, I normally use a wrapper class to do almost all of the above code, but the last two lines apply to part of your question.
As far as retrieving that data later based on the ID selected: well you can simply use a DataSet (or DataTable, my preference) class member variable so the data is stored the from the initial load and iterate through the table looking for the row that matches the ID you're wanting information from.

how to create a list within a list

Hello this is my first time posting so bear with me if I'm not so on point.
Here is my question:
I'm trying to create a list within a list in asp.net,
something like
callList(a).part(b).Number
callList(a).part(b).Desc
I have service calls and each of these calls can have multiple parts listed in them.
Right now the class structure is something like
public class calls
somevars.....
public class part
public Number as integer
public desc as String
end class
end class
To create the call themselves I have
callList As New List(Of calls)
callList.add(calls)
How would I add multiple parts for each call?
Maybe this is what you are looking for. I used different names, but you'll figure it out :)
Public Class clsContent
Public Name As String
Public listOfCounteries As List(Of clsCountry)
End Class
Public Class clsCountry
Public countryName As String
End Class
Class Program
Private Shared Sub Main(args As String())
Dim _countryEgypt As New clsCountry()
_countryEgypt.countryName = "Egypt"
Dim _countrySudan As New clsCountry()
_countrySudan.countryName = "Sudan"
Dim _cont As New clsContent()
_cont.Name = "Africa"
_cont.listOfCounteries = New List(Of clsCountry)()
_cont.listOfCounteries.Add(_countryEgypt)
_cont.listOfCounteries.Add(_countrySudan)
Dim _listOfContenents As New List(Of clsContent)()
_listOfContenents.Add(_cont)
Console.WriteLine((("Contenent: " + _listOfContenents(0).Name & " Country 1: ") + _listOfContenents(0).listOfCounteries(0).countryName & " Country 2: ") + _listOfContenents(0).listOfCounteries(1).countryName)
Console.Read()
End Sub
End Class
I think what you're looking for is described here under nested lists (slight syntax changes for ASP.net vs VB.net)
add a list into another list in vb.net
EDIT:
If you have trouble with the link, what you'll find there is:
Hope this helps
Update Reading them is like accessing any other list. To get the
first field in the first record
return records(0)(0)
second field in first record return records(0)(1)
etc . . .
Dim listRecord As New List(Of String)
listRecord.Add(txtRating.Text)
listRecord.Add(txtAge.Text)
listRace.Add(listRecord)
Dim records as new List(of List(of String))
records.Add(listRecord)
He creates a
List(Of String)
and then adds it to a
List(Of List(Of String))

Populate an Array of Object Based on DataReader Data

I am not sure how to phrase my question properly but I want to achieve something like this.
I have a class named Products
public class Products
private ID as Integer
private Name as String
Public Property ProductID()
Get
Return ID
End Get
Set(ByVal value)
ID = value
End Set
End Property
In one of my code behind pages, I am retrieving data from an SQL Command and placing the same into a datareader object.
How would I be able to declare the class so that each row in my datareader would actually be an instance of the said class?
Like for example:
Dim myProduct() as New Product
Dim intCnt as Integer
While datareaderData.read()
intCnt += 1
myProduct(intCnt) = new Product
myProduct(intCnt).ID = datareaderData("ID")
myProduct(intCnt).Name = datareaderData("Name")
End While
When I do the same, I am getting an error "Object Reference Not Set to an Instance of an Object.
I am quite stumped on this one. Any tips greatly appreciated. Thanks.
You should use an Arraylist or -better- a generic List(of Product).
Besides i would strongly recommend to set Option Strict On in your project's Compiler Settings.
Dim products As New List(Of Product)
While datareaderData.read()
Dim nextProduct As New Product
nextProduct.ProductID = CType(datareaderData("ID"), System.Int32)
nextProduct.Name = datareaderData("Name").ToString
products.add(nextProduct)
End While