Sort an arraylist of objects by one of the properties? - vb.net

Hi I have an object called item here is the code for it:
Public Class item
Private itemValue As String
Private urlfoundValue As String
Private typeValue As String
Private scorevalue As String
Public Sub New()
' Leave fields empty.
End Sub
Public Sub New(ByVal item As String, ByVal urlfound As String, ByVal type As String, ByVal score As String)
itemValue = item
urlfoundValue = urlfound
typeValue = type
scorevalue = score
End Sub
Public Property item() As String
Get
Return itemValue
End Get
Set(ByVal value As String)
itemValue = value
End Set
End Property
Public Property urlfound() As String
Get
Return urlfoundValue
End Get
Set(ByVal value As String)
urlfoundValue = value
End Set
End Property
Public Property type() As String
Get
Return typeValue
End Get
Set(ByVal value As String)
typeValue = value
End Set
End Property
Public Property score() As String
Get
Return scorevalue
End Get
Set(ByVal value As String)
scorevalue = value
End Set
End Property
I have an ArrayList of these items that I would like to sort in highest to lowest order by the Score property (is string but can be converted to int32).
The items are all store in this arraylist:
Public fullitem As New System.Collections.ArrayList()
Any suggestions on how to get the items in order by the score? Can be done in c# too.

A direct answer to your question is to use LINQ like this:
Dim orderdList = fullitem.Cast(Of item)() _
.OrderBy(Function(i As item) Convert.ToInt32(i.score))
fullitem = New System.Collections.ArrayList()
For Each item In orderdList
fullitem.Add(item)
Next
This uses Cast to obtain a generic IEnumerable<item> from the ArrayList which then enables you to use LINQ functions like OrderBy.
However, please note that ArrayList is now obsolete, and you should consider using List<Item> instead. If you do that then you can do something as simple as this:
Assuming you have the list defined like this:
Dim list = new List(Of item)()
You can sort it like this:
list = list.Cast(Of item)() _
.OrderBy(Function(i As item) Convert.ToInt32(i.score)) _
.ToList()

Related

Comparing list of class by string length and text comparison

I have a List(Of Abbreviation).
The class "Abbreviation" contains the string members "Input", "Output" and "CaseSensitive".
The class is stated below.
I would like to sort this list so that the class with the "Input"
"ZZZ"
comes before
"zz"
The comparison should thus first compare by string length, then by alphetical order, and then by CaseSensitive.
How could I sort the list this way?
Public Class Abbreviation
Implements IComparable
Private _sIn As String = String.Empty
Private _sOut As String = String.Empty
Private _bCaseSensitive As Boolean = False
Public Property Input() As String
Get
Return _sIn
End Get
Set(value As String)
_sIn = value
End Set
End Property
Public Property Output() As String
Get
Return _sOut
End Get
Set(value As String)
_sOut = value
End Set
End Property
Public Property CaseSensitive() As Boolean
Get
Return _bCaseSensitive
End Get
Set(value As Boolean)
_bCaseSensitive = value
End Set
End Property
Public Sub New(ByVal uInput As String, ByVal uOutput As String, ByVal uCaseSensitive As Boolean)
_sIn = uInput
_sOut = uOutput
_bCaseSensitive = uCaseSensitive
End Sub
End Class
First, you can simplify your code by using automatic properties. The compiler writes the get, set, and backer fields (the private fields). This is the preferred way in recent versions of Visual Studio if there is no extra code in the getter, setter.
Another small detail with your Sub New. It violates encapsulation to set the private fields directly. Always go through the Public Properties. There could be code in the setter that needs to run before storing the data in the private fields. Classes like to keep their data close to the vest in their private fields.
Example of Auto Implemented Properties
Public Property Input As String
Public Property Output As String
Public Property CaseSensitive As Boolean
The sort can be done in one line of code using a Linq query.
Dim orderedList = From abrev In lstAbreviations Order By abrev.Input.Lenght Descending Select abrev
To check the output...
For Each abrev As Player In orderedList
Debug.Print(abrev.Input)
Next
I think I got it, except the case sensitivity. CaseSensitive should come before CaseSensitive = False.
Public Class Abbreviation
Implements IComparable(Of Abbreviation)
Private _sIn As String = String.Empty
Private _sOut As String = String.Empty
Private _bCaseSensitive As Boolean = False
Public Function CompareTo(uOther As Abbreviation) As Integer _
Implements IComparable(Of Abbreviation).CompareTo
If uOther.Input.Length > Me.Input.Length Then
Return 1
ElseIf uOther.Input.Length < Me.Input.Length Then
Return -1
Else
If uOther.Input > Me.Input Then
Return 1
Else
Return -1
End If
End If
End Function

How to get a list from a linq to Entity Framework query using vb.net

I thought getting data from an SQL table in VB.Net would be easy, especially with Linq, but I just can't get it to work. I'm using a code-first model.
I have no idea why the following code gives me an error "Public member 'ToList' on type 'DbQuery(Of Company)' not found."
I can't even to a "For Each" over the query.
Dim lCompany1 = From proc In model1.Companies _
Where proc.Website = website _
Select proc
Dim products As IEnumerable(Of Company) = lCompany1.ToList()
This should work for you:
Dim lCompany1 = (From proc In model1.Companies
Where proc.Website = website).ToList()
I got it working with the following:
Dim con As String = ConfigurationManager.ConnectionStrings("Model1").ConnectionString
Dim db As New DataContext(con)
Dim a As Table(Of Catagory2)
a = db.GetTable(Of Catagory2)()
Dim dt As List(Of Catagory2) = a.AsQueryable.Where(Function(p) p.Town.Contains("something")).ToList()
And I used the following model:
Imports System
Imports System.Data.Linq.Mapping
<Table(name:="Category")> _
Public Class Catagory2
Private _Id As Integer
Private _Town As String
Private _Category As String
Private _Done As String
Private _State As String
Private _URL As String
<Column(IsPrimaryKey:=True, IsDbGenerated:=True)> _
Public Property Id() As Integer
Get
Return _Id
End Get
Set(ByVal value As Integer)
_Id = value
End Set
End Property
<Column(CanBeNull:=True)> _
Public Property Town() As String
Get
Return _Town
End Get
Set(ByVal value As String)
_Town = value
End Set
End Property
<Column(CanBeNull:=True)> _
Public Property Category() As String
Get
Return _Category
End Get
Set(ByVal value As String)
_Category = value
End Set
End Property
<Column(CanBeNull:=True)> _
Public Property State() As String
Get
Return _State
End Get
Set(ByVal value As String)
_State = value
End Set
End Property
<Column(CanBeNull:=True)> _
Public Property Done() As String
Get
Return _Done
End Get
Set(ByVal value As String)
_Done = value
End Set
End Property
<Column(CanBeNull:=True)> _
Public Property URL() As String
Get
Return _URL
End Get
Set(ByVal value As String)
_URL = value
End Set
End Property
End Class
It didn't work with the model created by Entity Framework's create code-first model.

Storing a value for each ComboBox item

In lack of a Value property I planned to use Classes for storing Text and Value properties for my ComboBox items. So far I've succeeded.
Here is my class:
Public Class clCombobox
Public cname As String
Public cvalue As Integer
Public Property Display() As String
Get
Return Me.cname
End Get
Set(ByVal value As String)
Me.cname = value
End Set
End Property
Public Property Value() As String
Get
Return Me.cvalue
End Get
Set(ByVal value As String)
Me.cvalue = value
End Set
End Property
Public Sub New(ByVal name As String, ByVal value As String)
cname = name
cvalue = value
End Sub
Public Overrides Function ToString() As String
Return cname
End Function
End Class
Data is being added to the ComboBox like this:
cmbComboxBox.Items.Add(New clCombobox("Text", 1))
It seems like this works so far. But how do I get data back. Like if I want the value of the selected CheckBox item?
I tried using:
CType(cmbCombobox.SelectedItem, clCombobox).Value()
Did not work.
As per the documentation, use the SelectedItem property to retrieve the object that you stored in it.
Code to retrieve value you want:
Dim selectedItem as clCombobox = CType(cmbComboBox.SelectedItem, clCombobox)
Dim value As Integer = selectedItem.cvalue

Convert List(of T) into comma-separated string of Id's

I have a number of classes that all implement the same interface. e.g.
Public Class IncidentAsset
Implements IModelWithIdentity
Private _assetId As Int16
Private _otherAsset As String
Private _asset As Asset
Public Property AssetId() As Int16
Get
Return _assetId
End Get
Set(ByVal value As Int16)
_assetId = value
End Set
End Property
Public Property OtherAsset() As String
Get
Return _otherAsset
End Get
Set(ByVal value As String)
_otherAsset = value
End Set
End Property
Public Property Asset() As Asset
Get
Return _asset
End Get
Set(ByVal value As Asset)
_asset = value
End Set
End Property
Public Function GetId() As String Implements IModelWithIdentity.GetId
Return _assetId.ToString()
End Function
End Class
I have another object with a list of these objects.
Public Property IncidentAssetsDamaged() As List(Of IncidentAsset)
Get
Return _incidentAssetsDamaged
End Get
Set(ByVal value As List(Of IncidentAsset))
_incidentAssetsDamaged = value
End Set
End Property
I need to write a method that will return a comma-separated string of Id's using the GetId() method of the interface.
This is what I have so far:
Public Shared Function ToCommaSeparatedStringOfIds(Of T)(ByVal collection As List(Of T)) As String
Dim array As List(Of String) = New List(Of String)
For Each obj As IModelWithIdentity In collection
array.Add(obj.GetId())
Next
Return String.Join(",", array.ToArray)
End Function
Is there a better way of doing this in VB.NET using .NET 2.0?
There are few options I can see. If you specify the capacity of the list, the performance will be increased. Because List.Add() takes some extra steps to resize the collection.
Why not use a stringbuilder, and append comma at the end of each id's.
Dim builder As New StringBuilder()
For Each obj As IModelWithIdentity In collection
builder.Append(obj.GetId()).append(",")
Next
Dim res = builder.ToString()
But this may add an extra comma at the end.
You can sort this out by using an indexer, and conventional for loop.
Dim builder As New StringBuilder()
For i = 0 To collection.Count - 2
builder.Append(collection(i).GetId()).append(",")
Next
builder.Append(collection(collection.Count -1))
Dim res = builder.ToString()
This is logically right. Please benchmark this and do let know the results.

how to add value to combobox item

How can I add data value of each item to combobox in Visual Basic 2010?
Like html drop-down box.
Or is there anyway to add values to each item ?
I am adding item from MySQL database like this:
Command = New MySqlCommand("SELECT * FROM `maillist` WHERE l_id = '" & id & "'", connection)
Command.CommandTimeout = 30
Reader = Command.ExecuteReader()
If Reader.HasRows = True Then
While Reader.Read()
ComboBox1.Items.Add(Reader("name"))
End While
End If
I need to add Reader("ID") as value of each item...
Although this question is 5 years old I have come across a nice solution.
Use the 'DictionaryEntry' object to pair keys and values.
Set the 'DisplayMember' and 'ValueMember' properties to:
Me.myComboBox.DisplayMember = "Key"
Me.myComboBox.ValueMember = "Value"
To add items to the ComboBox:
Me.myComboBox.Items.Add(New DictionaryEntry("Text to be displayed", 1))
To retreive items like this:
MsgBox(Me.myComboBox.SelectedItem.Key & " " & Me.myComboBox.SelectedItem.Value)
I am assuming that you are wanting to add items to a ComboBox on an Windows form. Although Klaus is on the right track I believe that the ListItem class is a member of the System.Web.UI.WebControls namespace. So you shouldn't be using it in a Windows forms solution. You can, however, create your own class that you can use in its place.
Create a simple class called MyListItem (or whatever name you choose) like this:
Public Class MyListItem
Private mText As String
Private mValue As String
Public Sub New(ByVal pText As String, ByVal pValue As String)
mText = pText
mValue = pValue
End Sub
Public ReadOnly Property Text() As String
Get
Return mText
End Get
End Property
Public ReadOnly Property Value() As String
Get
Return mValue
End Get
End Property
Public Overrides Function ToString() As String
Return mText
End Function
End Class
Now when you want to add the items to your ComboBox you can do it like this:
myComboBox.Items.Add(New MyListItem("Text to be displayed", "value of the item"))
Now when you want to retrieve the value of the selected item from your ComboBox you can do it like this:
Dim oItem As MyListItem = CType(myComboBox.SelectedItem, MyListItem)
MessageBox.Show("The Value of the Item selected is: " & oItem.Value)
One of the keys here is overriding the ToString method in the class. This is where the ComboBox gets the text that is displayed.
Matt made an excellent point, in his comment below, about using Generics to make this even more flexible. So I wondered what that would look like.
Here's the new and improved GenericListItem class:
Public Class GenericListItem(Of T)
Private mText As String
Private mValue As T
Public Sub New(ByVal pText As String, ByVal pValue As T)
mText = pText
mValue = pValue
End Sub
Public ReadOnly Property Text() As String
Get
Return mText
End Get
End Property
Public ReadOnly Property Value() As T
Get
Return mValue
End Get
End Property
Public Overrides Function ToString() As String
Return mText
End Function
End Class
And here is how you would now add Generic items to your ComboBox. In this case an Integer:
Me.myComboBox.Items.Add(New GenericListItem(Of Integer)("Text to be displayed", 1))
And now the retrieval of the item:
Dim oItem As GenericListItem(Of Integer) = CType(Me.myComboBox.SelectedItem, GenericListItem(Of Integer))
MessageBox.Show("The value of the Item selected is: " & oItem.Value.ToString())
Keep in mind that the type Integer can be any type of object or value type. If you want it to be an object from one of your own custom classes that's fine. Basically anything goes with this approach.
If you want to use SelectedValue then your combobox must be databound.
To set up the combobox:
ComboBox1.DataSource = GetMailItems()
ComboBox1.DisplayMember = "Name"
ComboBox1.ValueMember = "ID"
To get the data:
Function GetMailItems() As List(Of MailItem)
Dim mailItems = New List(Of MailItem)
Command = New MySqlCommand("SELECT * FROM `maillist` WHERE l_id = '" & id & "'", connection)
Command.CommandTimeout = 30
Reader = Command.ExecuteReader()
If Reader.HasRows = True Then
While Reader.Read()
mailItems.Add(New MailItem(Reader("ID"), Reader("name")))
End While
End If
Return mailItems
End Function
Public Class MailItem
Public Sub New(ByVal id As Integer, ByVal name As String)
mID = id
mName = name
End Sub
Private mID As Integer
Public Property ID() As Integer
Get
Return mID
End Get
Set(ByVal value As Integer)
mID = value
End Set
End Property
Private mName As String
Public Property Name() As String
Get
Return mName
End Get
Set(ByVal value As String)
mName = value
End Set
End Property
End Class
Instead of adding Reader("Name") you add a new ListItem. ListItem has a Text and a Value property that you can set.
Yeah, for most cases, you don't need to create a class with getters and setters. Just create a new Dictionary and bind it to the data source. Here's an example in VB using a for loop to set the DisplayMember and ValueMember of a combo box from a list:
Dim comboSource As New Dictionary(Of String, String)()
cboMenu.Items.Clear()
For I = 0 To SomeList.GetUpperBound(0)
comboSource.Add(SomeList(I).Prop1, SomeList(I).Prop2)
Next I
cboMenu.DataSource = New BindingSource(comboSource, Nothing)
cboMenu.DisplayMember = "Value"
cboMenu.ValueMember = "Key"
Then you can set up a data grid view's rows according to the value or whatever you need by calling a method on click:
Private Sub cboMenu_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboMenu.SelectionChangeCommitted
SetListGrid(cboManufMenu.SelectedValue)
End Sub
Now you can use insert method instead add
' Visual Basic
CheckedListBox1.Items.Insert(0, "Copenhagen")