vb.net 2003 Arraylist of structure which have an arraylist - vb.net

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

Related

Binding DatagridView to List Provides "Extra" columns at runtime

I have a list of objects called "TournamentPlayers" (derived from a class "PlayerInfo") in my project.
I have applied the following code to bind the lstTournPlayers to a DataGridView:
' Bind List of TournamentPlayers to Datagridview
Dim bindingList = New BindingList(Of TournamentPlayers)(lstTournPlayers)
Dim source = New BindingSource(bindingList, Nothing)
dgvPlayers.DataSource = source
dgvMembershipNo.DataPropertyName = "strMembershipNo"
dgvPlayerName.DataPropertyName = "strMembershipName"
Found from an answer here on SO, but repurposed: https://stackoverflow.com/a/16695971/692250
However, I noticed that after setting up the columns within the datagrid view, I get this weird column heading now:
My question is: how can I bind the parts of the list to this datagridview.
For anyone interested here is the schema of the list:
Public Class PlayerInfo
Public strPlayerFirstName As String
Public strPlayerLastName As String
Public strMembershipNo As String
Public strMembershipName As String
End Class
Public Class TournamentPlayers : Inherits PlayerInfo
Public intStatus As Integer = 0
Public intByeRounds As Integer
Public intTeamID As Integer
End Class

SortedSet in Class does not expose correctly

I have a weird problem that I can't seem to figure out. Even weirder is that I'm fairly sure it has worked in the past, but not anymore.
I have a class where I define a variable as SortedSet. In a function, I can reference the variable, but its SortedSet attributes are not exposed. If I use them anyway, some of them work, others don't. If I create that variable inside my function, all works as expected.
This is the code:
Public Class MyTest
Public MySortedSet = New SortedSet(Of String)()
Public Sub New()
Dim MySortedSet2 = New SortedSet(Of String)()
'Constructor. To use this, add Dim MyTest As MyTest to the Form1_load sub.
Me.MySortedSet.add("Test")
For Each Item In Me.MySortedSet
MsgBox(Item) 'This does print Test
Next Item
Me.MySortedSet.add '.add not exposed
MySortedSet2.add '.add is exposed
End Sub
End Class
See the screenshot below. The first example only has 4 items, where the 2nd example has a full list of parameters. I need to fix this using the first example, so the ElementAt one works. It works in the second example, but not in the first. It gives the error that ElementAt is not part of this object.
How can I get the full list of parameters for me.MySortedSet.??????
You should declare MySortedSet as a Property:
Public Class MyTest
Public Property MySortedSet As New SortedSet(Of String)()
Public Sub New()
Dim MySortedSet2 As New SortedSet(Of String)()
Me.MySortedSet.Add("Test")
For Each item As String In Me.MySortedSet
Debug.WriteLine(item)
Next item
Me.MySortedSet.Add("Test")
MySortedSet2.Add("Test")
End Sub
End Class
You should also indicate variable types every time you declare a variable, even in a For Each statement.

Reference to an attribute of a class by means of a string containing the name of the property

Let's take a very short example of a class like this:
Public Class The_Class1
Public Property ID As Integer
Public Property Property1_Integer As Integer
Public Property Property2_Single As Single
End Class
Somewhere else, I have a dictionary containing instances of The_Class1, like this:
Public Dictionary_Class1 As New Dictionary(Of Integer, The_Class1)
I want to perform an operation over Property1_Integer on all of the members inside Dictionary_Class1. Also, I want to perform the very same operation over Property2_Single, so I would like to create a function to perform such operation, and somehow instruct VB to use a given property on every call.
Can you think of an elegant way to do that?
Edit: Let's say, for example, that the operation that I want to perform is the sum of every Property1_Integer or Property2_Single of the members inside the dictionary. What I really really want to do is to determine if all of the values are the same, or if there is at least one that is different.
You can use Reflection, but it's not as clean as you may imagine. Here's some skeleton code you can adapt to your needs:
Public Class The_Class1
Public Property ID As Integer
Public Property Property1_Integer As Integer
Public Property Property2_Single As Single
End Class
Private Sub SetProperty1_Integer()
Dim myClassInstance As New The_Class1
Dim myType As Type = GetType(The_Class1)
Dim propertyInfo As System.Reflection.PropertyInfo = myType.GetProperty("Property1_Integer")
propertyInfo.SetValue(myClassInstance, 1)
MessageBox.Show(myClassInstance.Property1_Integer.ToString)
End Sub
Have fun!

VBA Dictionary - Adding an item overwrites all items

I have a Problem with a Dictionary. If I add an Object to the Dictionary, it overwrites the whole containing Items with the added item.
After adding all elements, the Dictionary contains the right number of items, but the items are all the last added item.
For Each shp In pg.Shapes
Dim tmp As New cls_dtyp_link
//Filling tmp with Variables - not Displayed - tmp.link_obj is the Key
If link_dic.Exists(tmp.link_obj) Then
Debug.Print "not added:" & tmp.link_obj
Else
link_dic.Add tmp.link_obj, tmp
End If
Next
The cls_dtyp_link Class:
Public link_ne As String
Public link_obj As String
Public link_ref As Visio.Shape
Public obj_left As String
Public obj_right As String
Public ref_left As Visio.Shape
Public ref_right As Visio.Shape
Public basekey_left As String
Public basekey_right As String
Public root_site_ne_left As String
Public root_site_ne_right As String
Public root_obj_left As String
Public root_obj_right As String
Public ref_root_left As Visio.Shape
Public ref_root_right As Visio.Shape
Public hops As Integer
Public geht_zu_konzentrator As Boolean
Thank you for your help!
The problem comes from the Dim tmp As New cls_dtyp_link statement: what is does is adding a reference to the existing cls_dtyp_link object, it does not instantiate a new one as you would expect. If you want to create a new object, kill the existing one explicitly at the end of your loop: Set cls_dtyp_link = Nothing. Then a new instance will be created every time you re-enter the loop.
Generally, declaring and instantiating in one go is considered bad practice in VBA, because of issues like the one you encountered. I would suggest Dim-ing the object outside the loop, and Set-ting it inside the loop.
Also, have a look here:
VBA: Difference in two ways of declaring a new object? (Trying to understand why my solution works)
I hope that helps!

VB.NET Add row data to public class / public field of type List(Of T) Object reference not set to an instance of an object

I am trying to add rows to a public class that has public fields and am getting an error: Object reference not set to an instance of an object
Public Class EmailRecipient
EmailAddress As String = ""
FullName As String = ""
End Class
Public Class EmailDetails
Public FromEmail As String = ""
Public ToEmails As List(Of Emails) = nothing
End Class
Public Sub SetEmailDetails
'Populate EmailRecipient Class
Dim er As New EmailRecipient
er.EmailAddress = "rodney#norespect.com"
er.FullName = "Rodney Dangerfield"
'Populate EmailDetails Class
Dim ed As New EmailDetails
ed.FromEmail = "sender#danger.com" 'This works fine
ed.ToEmails.Add(er) 'Here error happens
End Sub
I'm guessing I need to create an instance of the EmailRecipient class before I can add an item to it.
Not sure how to do that with a Public Field in a Public Class??
It's been a rough day. I got up this morning, put a shirt on and a button fell off. I picked up my briefcase and the handle came off. I'm afraid to go to the bathroom.
Thanks for the help :-)
I'm guessing I need to create an instance of the EmailRecipient class
You already have an instance of the EmailRecipient class. That's your er variable. You actually have two errors here. First, you explicitly set ToEmails to Nothing:
Public ToEmails As List(Of Emails) = nothing
This means that your ToEmails variable is a Null Reference. It doesn't have an actual object yet.
The second issue is that you shouldn't get that excpetion, because this shouldn't even compile. You define ToEmails as a List(Of Emails), but tried to add an object of type "EmailRecepient" to it. That should be a compiler error. If it's not, you need to turn Option Strict or Option Infer back on.
So what you really need is an instance of a the List(Of EmailRecipient) type. Fix the bad line of code like this:
Public ToEmails As New List(Of EmailRecipient)