vb,net my collection property in my class is throwing an error - vb.net

I am learning about collections, I have a Person class
Imports System
Imports System.Collections.Generic
Imports System.Text
Public Class Person
Public Sub New()
End Sub
Public Sub New(ByVal id As Integer, ByVal first_name As String, ByVal mid_name As String, ByVal last_name As String, ByVal age As Short, ByVal sex As Char)
Me.p_id = id
Me.first_name = first_name
Me.mid_name = mid_name
Me.last_name = last_name
Me.p_age = age
Me.p_sex = sex
End Sub
Private p_id As Integer = -1
Private first_name As String = String.Empty
Private mid_name As String = String.Empty
Private last_name As String = String.Empty
Private p_age As Short = 0
Private p_sex As Nullable(Of Char) = Nothing
Public Property ID() As Integer
Get
Return p_id
End Get
Set(ByVal value As Integer)
p_id = value
End Set
End Property
Public Property FirstName() As String
Get
Return first_name
End Get
Set(ByVal value As String)
first_name = value
End Set
End Property
Public Property MiddleName() As String
Get
Return mid_name
End Get
Set(ByVal value As String)
mid_name = value
End Set
End Property
Public Property LastName() As String
Get
Return last_name
End Get
Set(ByVal value As String)
last_name = value
End Set
End Property
Public Property Age() As Short
Get
Return p_age
End Get
Set(ByVal value As Short)
p_age = value
End Set
End Property
Public Property Sex() As Nullable(Of Char)
Get
Return p_sex
End Get
Set(ByVal value As Nullable(Of Char))
p_sex = value
End Set
End Property
End Class
and an Employee Class where I define a Person property
Imports System
Imports System.Collections.Generic
Imports System.Text
Public Class Employee
Public Sub New()
End Sub
Public Sub New(ByVal id As Integer, ByVal companyName As String, ByVal office As String, colPerson As Person)
'Me._employeeid = id
'Me._companyName = companyName
'Me._office = office
End Sub
Private _employeeid As Integer = -1
Private _companyName As String = String.Empty
Private _office As String = String.Empty
Public Property Empoyee_ID() As Integer
Get
Return _employeeid
End Get
Set(ByVal value As Integer)
_employeeid = value
End Set
End Property
Public Property CompanyName() As String
Get
Return _companyName
End Get
Set(ByVal value As String)
_companyName = value
End Set
End Property
Public Property Office() As String
Get
Return _office
End Get
Set(ByVal value As String)
_office = value
End Set
End Property
Property colPerson As List(Of Person)
End Class
How can i populate the persons class as well
Sub Main()
Dim pList As List(Of Person) = New List(Of Person)()
Dim thePerson As New List(Of Person) From
{
New Person With {.Age = 29, .FirstName = "John", .LastName = "Shields", .MiddleName = "", .Sex = "M", .ID = 1},
New Person With {.Age = 34, .FirstName = "Mary", .LastName = "Matthew", .MiddleName = "L", .Sex = "F", .ID = 2},
New Person With {.Age = 55, .FirstName = "Amber", .LastName = "Carl", .MiddleName = "P", .Sex = "M", .ID = 3},
New Person With {.Age = 12, .FirstName = "Kathy", .LastName = "Berry", .MiddleName = "O", .Sex = "F", .ID = 4}
}
'pList.Add(New Person(1, "John", "", "Shields", 29, "M"c))
'pList.Add(New Person(2, "Mary", "Matthew", "Jacobs", 35, "F"c))
'pList.Add(New Person(3, "Amber", "Carl", "Agar", 25, "M"c))
'pList.Add(New Person(4, "Kathy", "", "Berry", 21, "F"c))
'pList.Add(New Person(5, "Lena", "Ashco", "Bilton", 33, "F"c))
'pList.Add(New Person(6, "Susanne", "", "Buck", 45, "F"c))
'pList.Add(New Person(7, "Jim", "", "Brown", 38, "M"c))
'pList.Add(New Person(8, "Jane", "G", "Hooks", 32, "F"c))
'pList.Add(New Person(9, "Robert", "", "", 31, "M"c))
'pList.Add(New Person(10, "Cindy", "Preston", "Fox", 25, "F"c))
'pList.Add(New Person(11, "Gina", "", "Austin", 27, "F"c))
'pList.Add(New Person(12, "Joel", "David", "Benson", 33, "M"c))
'pList.Add(New Person(13, "George", "R", "Douglas", 55, "M"c))
'pList.Add(New Person(14, "Richard", "", "Banks", 22, "M"c))
'pList.Add(New Person(15, "Mary", "C", "Shaw", 39, "F"c))
'
'loop through the list
' PrintOnConsole(pList, "1. --- Looping through all items in the List<T> ---")
'
'Filtering List(T) using a single condition - (Age > 35)
'Dim filterOne As List(Of Person) = pList.FindAll(Function(p As Person) p.Age > 35)
'PrintOnConsole(filterOne, "2. --- Filtering List<T> on single condition (Age > 35) ---")
''
'' Filtering List(T) on multiple conditions (Age > 35 and Sex is Female)
'Dim filterMultiple As List(Of Person) = pList.FindAll(Function(p As Person) p.Age > 35 AndAlso p.Sex = "F"c)
'PrintOnConsole(filterMultiple, "3. --- Filtering List<T> on multiple conditions (Age > 35 and Sex is Female) ---")
''
''Sorting List(T) (Sort on FirstName)
'Dim sortFName As List(Of Person) = pList
'sortFName.Sort(Function(p1 As Person, p2 As Person) p1.FirstName.CompareTo(p2.FirstName))
'PrintOnConsole(sortFName, "4. --- Sort List<T> (Sort on FirstName) ---")
'
'Sorting List(T) descending (Sort on LastName descending)
'Dim sortLNameDesc As List(Of Person) = pList
'sortLNameDesc.Sort(Function(p1 As Person, p2 As Person) p2.LastName.CompareTo(p1.LastName))
'PrintOnConsole(sortLNameDesc, "5. --- Sort List<T> descending (Sort on LastName descending) ---")
''Add new List(T) to existing List(T)
'Dim newList As List(Of Person) = New List(Of Person)()
'newList.Add(New Person(16, "Geoff", "", "Fisher", 29, "M"c))
'newList.Add(New Person(17, "Samantha", "Carl", "Baxer", 32, "F"c))
'pList.AddRange(newList)
'PrintOnConsole(pList, "6. --- Add new List<T> to existing List<> ---")
''Remove multiple items from List(T) based on condition (remove male employees)
'Dim removeList As List(Of Person) = pList
'removeList.RemoveAll(Function(p As Person) p.Sex = "M"c)
'PrintOnConsole(removeList, "7. --- Remove multiple items from List<> based on condition ---")
'' Create Read Only List(T)
'Console.WriteLine("Create Read Only List<>")
'Dim personReadOnly As IList(Of Person) = pList
'Console.WriteLine("Before - Is List Read Only? True or False : " & personReadOnly.IsReadOnly)
'personReadOnly = pList.AsReadOnly()
'Console.WriteLine("After - Is List Read Only? True or False : " & personReadOnly.IsReadOnly & "</br>")
'
'Dim pList1 As New Person
Dim emp As New List(Of Employee)
Dim r As New Employee
r.CompanyName = "zac"
r.Office = "home"
r.Empoyee_ID = 1
'Dim pList1 = New Person(1, "John", "", "Shields", 29, "M"c)
r.colPerson.Add(New Person(1, "John", "", "Shields", 29, "M"c))---> Gives error
emp.Add(r)
'
Dim i As New Employee
i.CompanyName = "zac1"
i.Office = "home1"
i.Empoyee_ID = 2
i.colPerson.Add(New Person(3, "Amber", "Carl", "Agar", 25, "M"c))
pList.Add(New Person(4, "Kathy", "", "Berry", 21, "F"c))
emp.Add(i)
'
Dim t As New Employee
t.CompanyName = "zac2"
t.Office = "home2"
t.Empoyee_ID = 2
pList.Add(New Person(5, "Lena", "Ashco", "Bilton", 33, "F"c))
pList.Add(New Person(6, "Susanne", "", "Buck", 45, "F"c))
emp.Add(t)
For Each item In emp
'item.CompanyName = "zac"
'item.Office = "home"
'item.colperson.Where(Function(x) x.ID = 17)
'Console.WriteLine("employee with person collection: " & item.CompanyName & " " & item.Office & " " & item.colperson.Where(Function(x) x.ID = 17).ToString & "</br>")
Console.WriteLine("employee with person collection: " & item.CompanyName & " " & item.Office & "</br>")
Next
End Sub

r.colPerson.Add(New Person(1, "John", "", "Shields", 29, "M"c))---> Gives error
It gives an error because even though colPerson is declared to be capable of holing a list of people, it hasn't actually been set to be a list of people, so it's currently Nothing, and you can't call methods on something that is Nothing
Property colPerson As New List(Of Person)
^^^
Add a New directive to ensure it's declared and initialized to an instance of a List
Also, please:
Don't put "col" in names
Use a plural name for List(Of Thing) - this is a list of person so it should at least be called People, but also perhaps state what kind of people they are. For example if this Employee was recommended by a few people, call it RcommendedByPeople
Only use Collection in a name if you're writing a class that is a collection, such as Microsoft did when they wrote MatchCollection - a collection of regular expression Matches
Be definite about whether the property is public, private etc
i.e.
Public Property RcommendedByPeople As New List(Of Person)

Related

object Collection Containing a List of IDs Linq

I have a list box and the user is able to multi-select. I want to use Linq and bring back the records of the selected IDs that the user selects. I need to bring back the full object record for each selected ID
Here is the contact object along with collection object
Namespace MODEL
<System.Serializable()> _
Public Class ContactCollection
Inherits System.Collections.ObjectModel.Collection(Of Contact)
Implements IList(Of Contact)
End Class
End Namespace
Namespace MODEL
<System.Serializable()> _
Public Class Contact
Private mContactID As Int32 = 0
Private mFirstName As String
Private mLastName As String
Public Property ContactID As Int32
Get
Return mContactID
End Get
Set(value As Int32)
mContactID = value
End Set
End Property
Public Property FirstName As String
Get
Return mFirstName
End Get
Set(value As String)
mFirstName = value
End Set
End Property
Public Property LastName As String
Get
Return mLastName
End Get
Set(value As String)
mLastName = value
End Set
End Property
End Class
End Namespace
Adding 5 Records to the collection object
Dim objCollection As New MODEL.ContactCollection
Dim obj As New MODEL.Contact
objCollection.Add(New MODEL.Contact With {
.ContactID = 1, _
.FirstName = "John", _
.LastName = "Smtih" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 2, _
.FirstName = "Mark", _
.LastName = "Davis" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 3, _
.FirstName = "Tom", _
.LastName = "Howe" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 4, _
.FirstName = "Jerry", _
.LastName = "Thomas" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 5, _
.FirstName = "Jane", _
.LastName = "Marry" _
})
This is the selected contact List from the list box
Dim lstContacts As New List(Of Integer)
lstContacts.Add(2)
lstContacts.Add(4)
I am not sure what to do at this point with Linq to find the values. I think I have to use contains but I have tried may different ways but I was unable to get the values.
I have tried this Linq but does not work or bring any records back
Dim objSearch from SearchContacts in objCollection
Where (lstContacts.Contains(SearchContacts.ContactID))
To get the Ids, try that :
Dim ids As IEnumerable(Of Int32) = myListBox.SelectedItems _
.OfType(Of Contact)() _
.Select( Function(c) c.ContactID ) _
Edit
If you want the Contacts, you can just just :
Dim ids As IEnumerable(Of Contact) = myListBox.SelectedItems _
.OfType(Of Contact)()
And if you want the contacts in a separate copied collection, you can :
Dim ids As List(Of Contact) = myListBox.SelectedItems _
.OfType(Of Contact)() _
.ToList()
Last (if think this is your real question - just tell and I erase everything above)
Dim selectedContacts As IEnumerable(Of MODEL.Contact) = From contact In objCollection
Join id In lstContacts
On contact.ContactID Equals id
Select contact

VB.Net : How do you bind a dictionary collection to a Combobox?

I am trying to bind this dictionary collection to a combobox but the display
is not correct. The displayMember should be the ProvName and the ValueMember should be the key.
Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
Dim Country1 As Dictionary(Of String, Province)
Country1 = Module1.CreateCountry
'Display results in combox
ComboBox3.DataSource = New BindingSource(Country1, Nothing)
ComboBox2.DisplayMember = "Value"
ComboBox2.ValueMember = "Key"
End Sub
Module Module1
Public provinces As CollectionBase
Function CreateCountry() As Dictionary(Of String, Province)
Dim Country As New Dictionary(Of String, Province)
Dim Prov As Province
Prov = New Province
With Prov
.Abbrv = "Qc"
.ProvName = "Quebec"
.Population = "7 500 000"
.Region = "East"
End With
Country.Add(Prov.Abbrv, Prov)
Prov = New Province
With Prov
.Abbrv = "BC"
.ProvName = "British Columbia"
.Population = "4 500 000"
.Region = "West"
End With
Country.Add(Prov.Abbrv, Prov)
Prov = New Province
With Prov
.Abbrv = "NS"
.ProvName = "Nova Scotia"
.Population = "2 000 000"
.Region = "Maritimes"
End With
Country.Add(Prov.Abbrv, Prov)
Prov = New Province
With Prov
.Abbrv = "AB"
.ProvName = "Alberta"
.Population = "5 500 000"
.Region = "Prairies"
End With
Country.Add(Prov.Abbrv, Prov)
Return Country
End Function
End Module
Public Class Province
Public Property Abbrv As String
Public Property ProvName As String
Public Property Population As String
Public Property Region As String
Public Overrides Function ToString() As String
Return ProvName
End Function
End Class
Here is the sample source code:
'Declare and Fill a generic Dictionary
Dim dictionary As New Dictionary(Of String, Integer)
dictionary.Add("one", 1)
dictionary.Add("two", 2)
dictionary.Add("three", 3)
dictionary.Add("four", 4)
dictionary.Add("five", 5)
dictionary.Add("six", 6)
dictionary.Add("seven", 7)
dictionary.Add("eight", 8)
'Initialize DisplayMember and ValueMember of an existing combobox to be filled with dictionary values
cboCombo.DisplayMember = "Key"
cboCombo.ValueMember = "Value"
'Bind the combobox to dictionary
cboCombo.DataSource = New BindingSource(dictionary, Nothing)
'Now I can assign the selected value of combobox with this simple command:
cboCombo.SelectedValue = 4
'I can also retrive the selected value with:
value = cboCombo.SelectedValue
If this help you mark as answer
This is just an example of using a dictionary to bind data to a combobox.
Declare dictionary object and initialize it with values as follows:
Dim dcItems As New Dictionary(Of String, Integer)
lstTPAType.Add("Select", -1)
lstTPAType.Add("Item 1", 0)
lstTPAType.Add("Item 2", 1)
lstTPAType.Add("Item ", 2)
cmbMyCombo.DataSource = New BindingSource(dcItems, Nothing)
cmbMyCombo.ValueMember = "Value"
cmbMyCombo.DisplayMember = "Key"
Hope this generic solution will help developers looking for it.

Dictionary (of integer,class) type

I would like to save variables in a simple method before adding to a datatable. Is it possible to have a dictionary (of integer,class) type like the code below? I can then loop through the keys to get the variables.Any ideas please?
Public Class CONTACTS
Dim FIRST_NAME As String
Dim SURNAME As String
Dim DOB As Date
Dim AGE As Integer
End Class
Sub TEST_DICT()
Dim dctCONTACTS As Dictionary(Of Integer, List OF Class(CONTACTS)) 'not sure how to declare this
dctCONTACTS.Add(1, "MARK").FIRST_NAME 'not sure how to savevariable
dctCONTACTS.Add(1, "SMITH").SURNAME
dctCONTACTS.Add(1, "5 May 1995").DOB
dctCONTACTS.Add(1, 31).AGE
dctCONTACTS.Add(2, "ANNE").FIRST_NAME
dctCONTACTS.Add(2, "MOORE").SURNAME
dctCONTACTS.Add(3, "5 April 1990").DOB
dctCONTACTS.Add(4, 26).AGE
Dim X = dctCONTACTS(1).AGE
End Sub
You really you go look at the many many "how to code VB.NET" resources online rather than ask basic syntax questions here.
Here is your code in valid VB.NET:
Public Class CONTACTS
Public FIRST_NAME As String
Public SURNAME As String
Public DOB As Date
Public AGE As Integer
End Class
Sub TEST_DICT()
Dim dctCONTACTS As New Dictionary(Of Integer, List(Of CONTACTS))
dctCONTACTS.Add(1, New List(Of CONTACTS) From
{
New CONTACTS() With { .FIRST_NAME = "MARK", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 },
New CONTACTS() With { .FIRST_NAME = "JOE", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 },
New CONTACTS() With { .FIRST_NAME = "SARAH", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 }
})
dctCONTACTS.Add(2, New List(Of CONTACTS) From
{
New CONTACTS() With { .FIRST_NAME = "BOB", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 },
New CONTACTS() With { .FIRST_NAME = "SUE", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 },
New CONTACTS() With { .FIRST_NAME = "ABIGAIL", .SURNAME = "SMITH", .DOB = New DateTime(1995, 5, 5), .AGE = 31 }
})
Console.WriteLine(dctCONTACTS(2)(0).FIRST_NAME)
End Sub
Running TEST_DICT gives BOB in this case.

Create own data examples in LinqPad

I have a class (vb.net) with some data that I want to query in LinqPad. I already worked with some examples as the one from "Linq in Action" so they work with some kind of classes with data as well to explain queries. But I just cannot find anything about how to import or write your own classes. Could anyone help me here?
My Class looks like:
Public Class Employee
Public Property ID As Integer
Public Property Salery As Integer
Public Property Name As String
Public Property Department As String
Public Property Gender As String
Public Shared Function GetAllEmployees() As List(Of Employee)
Return New List(Of Employee) From { _
New Employee With {.ID = 1, .Name = "Mark", .Department = "HR", .Gender = "Male", .Salery = 12000},
New Employee With {.ID = 2, .Name = "Sandra", .Department = "IT", .Gender = "Female", .Salery = 2000} _
}
End Function
End Class
You might be missing a couple things about using LINQPad:
Set the Language to "VB Program" and put classes where the comment says to.
Use the Dump method to output an expression. (For "VB Expression", Dump is called automatically.)
Here is an example. (Note, you might be using that SQL-looking syntax.)
Sub Main
Employee.GetAllEmployees() _
.Where(Function (employee) employee.Department = "HR") _
.Dump()
Dim hrEmployees = From employee In Employee.GetAllEmployees()
Where employee.Department = "HR"
hrEmployees.Dump()
End Sub
' Define other methods and classes here
Public Class Employee
Public Property ID As Integer
Public Property Salery As Integer
Public Property Name As String
Public Property Department As String
Public Property Gender As String
Public Shared Function GetAllEmployees() As List(Of Employee)
Return New List(Of Employee) From { _
New Employee With {.ID = 1, .Name = "Mark", .Department = "HR", .Gender = "Male", .Salery = 12000},
New Employee With {.ID = 2, .Name = "Sandra", .Department = "IT", .Gender = "Female", .Salery = 2000} _
}
End Function
End Class

How to get Lambda in LINQ to actually filter for dynamic linq

Example-I have a person class
Public Class Person
Private _fname As String
Public Property Fname() As String
Get
Return _fname
End Get
Set(ByVal value As String)
_fname = value
End Set
End Property
Private _lname As String
Public Property Lname() As String
Get
Return _lname
End Get
Set(ByVal value As String)
_lname = value
End Set
End Property
Private _age As Integer
Public Property Age() As Integer
Get
Return _age
End Get
Set(ByVal value As Integer)
_age = value
End Set
End Property
End Class
Dim people As New List(Of Person)
people.Add(New Person With {.Fname = "Alice", .Lname = "Apples", .Age = 1})
people.Add(New Person With {.Fname = "Bob", .Lname = "Banana", .Age = 2})
people.Add(New Person With {.Fname = "Charlie", .Lname = "Cherry", .Age = 3})
people.Add(New Person With {.Fname = "Dave", .Lname = "Durian", .Age = 4})
people.Add(New Person With {.Fname = "Eric", .Lname = "EggPlant", .Age = 10})
Dim filteredPerson = From person In people
filteredPerson.Where(Function(fp) fp.Fname = "Bob")
Dim finalList = filteredPerson.ToList
For Each p In finalList
Debug.Print("FNAME: " + p.Fname)
Next
This still returns all 5 people, like the where is not being applied, what am I doing wrong?
I would also like to be able to pass a list of names and return only those
Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")
Dim filteredPerson = From person In people
For Each s In searchList
Dim innerName As String = s
filteredPerson.Where(Function(fp) fp.Fname = innerName)
Next
Dim finalList = filteredPerson.ToList
For Each p In finalList
Debug.Print("FNAME: " + p.Fname)
Next
The problem is that Where doesn't change the collection. It returns the newly filtered collection.
Try this:
Dim filteredPerson = people.Where(Function(fp) fp.Fname = "Bob")
(By the way, I don't see anything dynamic in here... where are you using dynamic LINQ?)
To add multiple Where clauses, you'll want something like this:
Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")
Dim filteredPerson As IEnumerable(Of String) = people
For Each s In searchList
Dim innerName As String = s
filteredPerson = filteredPerson.Where(Function(fp) fp.Fname = innerName)
Next
Dim finalList = filteredPerson.ToList
For Each p In finalList
Debug.Print("FNAME: " + p.Fname)
Next
However, I don't believe that's actually what you want to do. Each Where clause is going to insist that Fname is the specified name - and it's not going to be both Bob and Dave! I think you actually want something which can be expressed much more simply:
Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")
Dim filteredPerson = people.Where(Function(fp) searchList.Contains(fp.Fname))
Dim finalList = filteredPerson.ToList
For Each p In finalList
Debug.Print("FNAME: " + p.Fname)
Next
All we want to know is whether Fname is in searchList, which is what Contains does.
Dim people As New List(Of Person)
people.Add(New Person With {.Fname = "Alice", .Lname = "Apples", .Age = 1})
people.Add(New Person With {.Fname = "Bob", .Lname = "Banana", .Age = 2})
people.Add(New Person With {.Fname = "Charlie", .Lname = "Cherry", .Age = 3})
people.Add(New Person With {.Fname = "Dave", .Lname = "Durian", .Age = 4})
people.Add(New Person With {.Fname = "Eric", .Lname = "EggPlant", .Age = 10})
Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")
dim filteredItems = from p in people _
join i in searchList on p.FName equals i _
select p
dim personFound as Person
for each personFound in filteredItems
Console.WriteLine(personFound.Lname)
next