Retrieving data from a VB.NET arraylist of objects - vb.net

I am trying to retrieve the correct value from an ArrayList of objects (.NET 1.1 Framework):
I have the following defined:
Public AlList As New ArrayList
Public Class ItemInfo
Public ItemNo As Int16
Public ItemType As String
Public Reports As Array
Public PDFs As Array
End Class
The form_load event code contains:
Dim AnItemObj As New ItemInfo
Then a loop that includes:
AnItemObj.ItemNo = AFile.RecordId
AnItemObj.ItemType = temp
AlList.Add(AnItemObj)
So I should now have an ArrayList of these objects, however if I try to retrieve the data:
MsgBox(AlList(5).ItemNo)
I always get the ItemNo of the last value in the list.
What am I missing?

Put the following code:
Dim AnItemObj As New ItemInfo
inside the loop which adds AnItemObj to the list.
When you add a reference type to a list, you are only adding the reference, not the value.
This means that if you add 10 times the same instance to a list, it will add 10 times the same reference to the list. But if afterward you still have a reference to this instance you can modify its properties and as all 10 entries in the list point to the same reference in memory, all 10 entries will be modified.

So, you've got:
Dim AnItemObj As New ItemInfo
For ...
AnItemObj.ItemNo = AFile.RecordId
AnItemObj.ItemType = temp
AlList.Add(AnItemObj)
Next
What is happening here is you're creating a single object, setting the values on it, and adding a reference to it, to your list. You're then changing your ItemInfo and addign another reference to the same item to your list
You need to construct a new object on each loop, loosely thus:
Dim AnItemObj As ItemInfo
For ...
AnItemObj = New ItemInfo
AnItemObj.ItemNo = AFile.RecordId
AnItemObj.ItemType = temp
AlList.Add(AnItemObj)
Next

Are you creating a new instance of iteminfo for each increment of the loop?

I can't see your full loop code but I imagine the cause is not setting AnItemObj to a New ItemInfo object. So you just end up modifying the same object and adding it the the list again (all items in the list point to the same object).
AnItemObj = New ItemInfo()
AnItemObj.ItemNo = AFile.RecordId
AnItemObj.ItemType = temp
AlList.Add(AnItemObj)

Related

Add classes to a collection

I have a class called "Transport":
Public Frequency As Double
Public SourceDest As String
Now, I want to read out some cells in Excel and fill a collection with these objects of that class.
Collection:
Dim JobList As New Collection
Sub:
Dim tmp As New Transport
For i = 1 To 20
tmp.Frequency = Round(Frequencies(i), 5)
tmp.SourceDest = Jobs(i)
JobList.Add tmp
Next
Unfortunately, it just adds the same class 20 times, but I want different classes. How can I solve this?
In general, I am new to VBA and all I want is to read two columns in a table, put the "pairs" together (like so: {Double, String}) in a kind of list {Double, String},{Double, String}, .... I tried types before, but apparently they can't be stored in collections, so I chose classes.
In order to create a different object of the class each time you loop, you have to 'tell' VBA to create it inside the loop.
In line 4 a new instance of Transport Class is created in each loop
Dim tmp As Transport
For i = 1 To 20
Set tmp = New Transport
tmp.Frequency = Round(Frequencies(i), 5)
tmp.SourceDest = Jobs(i)
JobList.Add tmp
Next

vb.net create objects in for each loop from partial info in Ienumerable

Summary:I want to create objects in a for each loop.
I have a class - Dashboard, which has some properties - length, height, etc.
This info is contained within an XML document, but my class' properties is only a small subset of the information in the XML.
I have created a Collection of XElement, and I can iterate over these, but how do I create my object on each iteration of the loop?
Dim Col_DashBoards As IEnumerable(Of XElement) = From XDashboard In XDocument.Load(filename).Descendants("dashboard")
For Each XDashboard In Col_DashBoards
'PseudoCode
Dim Xdashboard.Name as New DashboardClassObject
Xdashboard.Name.Height = XDashboard.Element("Height").value
...
Next
If I have understood your question correctly, you wish to create a new object based on a subset of data from within an XML document?
The below is a function that will generate a new DashboardClassObject for every matching node and populate that object. A list of type DashboardclassObject is returned.
Public Function GenerateDashBoardFromXML(filename as string) As List(Of DashboardClassObject)
Dim dashboardList As List(Of DashboardClassObject) = New List(Of DashboardClassObject)()
Dim Col_DashBoards As IEnumerable(Of XElement) = From XDashboard In XDocument.Load(filename)?.Descendants("dashboard")
For Each XDashboard In Col_DashBoards
Dim dashboard As DashboardClassObject = New DashboardClassObject () With {
.Name = XDashboard.Element("Height")?.value
}
dashboardList.Add(dashboard)
Next
return dashboardList
End Function
It should be noted that Null checking is used here. The below is only populated if the matching element is found. Null coalescing operator is also an option here.
.Name = XDashboard.Element("Height")?.value

Possible to add some sort of identification onto list items?

I'm just curious if it's possible to gather a list of data and put it into a list or array and easily pull them out using some variable(like a tag property on controls) on each item in the list rather than using the index. An example would be if i have many controls on a form and would like to populate the values using the list but instead of having to cross check a lot of different indicies(would take a lot of time) i could just assign the label to some 'tag like' variable for the list item.
Is this possible?
Lists in .NET, such as the List(Of T) class, only support storing one object per item. However, the beauty of them is, you can store any type of object that you want. If you need to store metadata with your data, simply create a new class that holds all the data for each item. For instance:
Public Class MyControlData
Public Property LabelText As String
Public Property Value As String
End Class
Then you can add the items to the list like this:
Dim dataList As New List(Of MyControlData)()
Dim item As New MyControlData()
item.LabelText = "Name"
item.Value = "Bob"
dataList.Add(item)
And you can read the data from the list like this:
For Each i As MyControlData in dataList
Label1.Text = i.LabelText
TextBox1.Text = i.Value
Next
I would use a Dictionary object so you can use a key to reference your data easily.
You can use LINQ:
Dim myTagControls = From ctrl In Me.Controls.Cast(Of Control)()
Where "your-tag".Equals(ctrl.Tag)
For Each ctrl In myTagControls
Console.WriteLine("Tag:{0} Name:{1}", ctrl.Tag, ctrl.Name)
Next

vb.net 2003 Arraylist of structure which have an arraylist

I have two structures
Public Structure myResearchData
Public batchName As String
Public arraylistRData As ArrayList
End Structure
Public Structure myResearchSubData
Public researchDescription As String
Public recordingDate As Date
Public book As String
Public page As String
Public year As String
Public fee As String
End Structure
I initialize them in a sub
Dim MyResearchDataAList As New ArrayList
Dim MyResearchData As myResearchData
MyResearchData.arraylistRData = New ArrayList
Dim MyResearchSubData As myResearchSubData
I have an arraylist of myResearchSubData which is MyResearchData.arraylistRData and added it inside MyResearchDataAList. But when I cleared MyResearchData.arraylistRData the arraylist inside MyResearchDataAList is also cleared. I thought that once it is added to MyResearchDataAList it will hold the arraylist but it is also clered. Below is the process that I have done.
MyResearchSubData.recordingDate = Date.Parse(Date)
MyResearchSubData.book = Book
MyResearchSubData.page = Page
MyResearchSubData.year = Year
MyResearchSubData.fee = Fee
Put data in the structure of MyResearchSubData
MyResearchData.arraylistRData.Add(MyResearchSubData)
Added it in MyResearchData.arraylistRData
MyResearchDataAList.Add(MyResearchData)
Added it in MyResearchDataAList
MyResearchData.arraylistRData.Clear()
Cleared MyResearchData.arraylistRData for new data to be put in but it also clears the arraylist inside MyResearchDataAList and didn't old the contents of the arraylist
Thanks in advance for those who can help me with this problem
That is happening because it is actually the same items being added to the array list, as they are added by reference. You want to actually add a COPY of each item to your arrayList.
I generally find the easiest way to do something like that is to add a clone of the object during a loop.
To do that you may need to implement ICloneable to get the proper copy. At the level of the myResearchSubData however, it appears that you can just use the memberwiseClone Method.
If you change the to a class instead of a structure you can use the clone like this:
Public Class myResearchSubData
Implements ICloneable
Public researchDescription As String
Public recordingDate As Date
Public book As String
Public page As String
Public year As String
Public fee As String
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone
End Function
End Class
Then you would want to loop through your original list of myResearchSubData and add its clone to the second list. Something like:
For Each item as myResearchSubData in MyResearchData.arraylistRData
MyResearchDataAList.Add(CType(item.Clone, myResearchSubData))
Next
If you want to continue to use the structures then I would use the same loop type and make a function that creates a new myResearchSubData and copies the data from the original over to the new one.
For Each item as myResearchSubData in MyResearchData.arraylistRData
MyResearchDataAList.Add(CloneStructure(item))
Next

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