Accessing properties of objects within a List<T> - c#

I'm trying to use a property of individual object instances stored within a List<T> object, but I can't seem to access the properties directly.
I have an object (sportsCarVehicle) which stores a user-defined name (strVehicleName) (amongst other properties, but that's not important) within itself. The object is then stored within a List<sportsCarVehicle> object called sportsCarVehicleStorage.
I need to access every instance of sportsCarVehicle in List<sportsCarVehicle> and pass the value of strVehicleName to a combo box on a form.
I assume I'll need some kind to loop to cycle through each instance and pass the name to the combo box, but my main issue is not being able to access the property I need. The sportsCarVehicle instances have no reference-able name.
One more thing I should note: the constructor for sportsCarVehicle is called within the sportsCarVehicleStorage.Add() method.
Any suggestions on how I could do this?

Cant you do this
List<string> lst = new List<string>{"Hello", "World"};
int len = lst[0].Length;
Here .Length is a property of string. As long as that property is public we can access it.
In your case
List<sportsCarVehicle> sportsCarVehicleStorage = new List<sportsCarVehicle>();
// Some code to populate list.
mycombobox.Items = sportsCarVehicleStorage
.Select(x => x.strVehicleName).ToArray();
Make Sure property strVehicleName is public in that class.

You can use foreach to loop through the list, assigning each member of the list to a named variable, like:
foreach (sportsCarVehicle scv in sportsCarVehicleStorage)
{
//scv is the name of the currently looping sportsCarVehicle object
//use scv.strVehicleName to access the property.
myComboBox.Items.Add(scv.strVehicleName);
}

foreach (SportsCarVehicle car in myListName)
{
//do stuff here
}
That's the most basic example, you can use PLINQ etc. to do it in a more streamlined way.

An alternative could be to bind the list of sportsCarVehicle directly to the comboBox, for example:
List<sportCarVehicle> sportsCarVehicleStorage= new List<sportsCarVehicle>;
// Set up list content here
// ...
myComboBox.DataSource = sportsCarVehicleStorage;
myComboBox.DisplayMember = "strVehicleName";

Related

Another class property call from base class list

I have a two class properdata and pprosecnddata both classes having property
I want to access product property from properdata class list object. How is it possible,below is my sample code
pupilc class ProperData
{
public string code{get;set;}
public List<ProSecndData>Secnd{get;set;}
}
public class ProSecndData
{
public string product{get;set;}
}
I am trying to call property like that
class Program
{
static void Main(string[] args)
{
ProperData.Secnd.Product = "Hello";
}
}
you cannot directly access property of Secnd as it is a list
you need to iterate or select the index of the List<Secnd>
you must initialize Secnd first and Secnd should have items in the list
properData.Secnd = new List<ProSecndData>();
so it can be access via
foreach(var second in properData.Secnd)
{
second.product = "hello";
}
//or
for(var i = 0; i < proderData.Secnd.Count(); i++)
{
properData.Secnd[i].product = "hello";
}
//or
var index = //0-length of list;
properData.Secnd[index].product = "hello";
if you want to have items first then add first on your Secnd List
properData.Secnd = new List<ProSecndData>();
properData.Secnd.Add(new ProSecndData{ product = "hello"});
then you now can iterate the list by using methods above
You are trying to access list as a single object, which is not possible.
you need to create single instance of your list class and then you can add string in that single instance.
properData.Secnd = new List<ProSecndData>();
ProSecndData proSecndData = new ProSecndData();
proSecndData.product = "Hello";
properData.Secnd.Add(proSecndData);
Actually I know the answer already, you have not created a constructor to initialise your List.
I'm guessing you get a object null ref error?
Create the constructor to initialise your list and it should be fine.
But in future, please post the error message (not the whole stack, just the actual error) as well as all the code required to repeat the issue. Otherwise you run the risk of getting your question deleted
(It should be deleted anyway because it could be considered a "what is a null ref err?" question).
Also you are accessing an item in a list like the list is that item (should be more like: ProperData.Secnd.elementAt(0).product, please also note the capitalisation of 'product' in the model vs your code.

Add object to ICollection and then Add ICollection to a List<> ASP.NET

I'm not sure if this is possible or even makes total sense, but I need to add an object let's call it Person to an ICollection List People and add the collection to a List<> , in order to have the collection of people in a List<> that also will contain other parameters.
I am not sure how to do this but I can show you what I have sketched so far.
public void addPeopleToList(string PersonId)
{
Person p = findPerson(PersonId); /*Method that takes the ID and
returns an object from another List*/
ICollection<People> ICollectionPeople; //Create the ICollection
ICollectionPeople.Add(p); //Add Person to Collection
List.Add(ICollectionPeople); //Add Collection to List
}
If this way is not the proper way to do it, I am open to all other suggestions.
It's probably easier if you simply told us what exactly you want to achieve, but anyway:
You need to assign a value to ICollectionPeople (also maybe it's worth renaming it and following the naming conventions). Maybe
ICollection<People> peopleCollection = new List<People>();
Though do you really need that explicit type? You could use var.
You need to create an instance of the list you want to add your collection of people to. Maybe
var list = new List<People>();
Then finally, use AddRange() like
list.AddRange(peopleCollection);
I think what you need is another class.. like...
public class PersonWithAttributes : Person {
// add attribute properties here
}
Then in your code above you would change List to be of type List<PersonWithAttributes> and instead of .Adding the collection you would call List.AddRange(ICollectionPeople). After which you would need to loop over the List items and add the extra attributes you were talking about.
Not sure but looks like you wanted to have a List<List<People>> .. if that's so then your code is missing initialization of the collection. You need to change a bit
public void addPeopleToList(string PersonId)
{
Person p = findPerson(PersonId); /*Method that takes the ID and
returns an object from another List*/
List<Person> ICollectionPeople = new List<Person>(); //Create the
ICollectionPeople.Add(p); //Add Person to Collection
List<List<Person>> personLists = new List<List<Person>>()
personLists.Add(ICollectionPeople); //Add Collection to List
}

ViewModel returns same values for all 500+ records to the view

I am new to using ViewModels, I have a new list here and am adding items to it by looping though a database table. The issue is that all the records that come back are identical using the same record over and over. What could be the issue and is this a good way to accomplish filling with data and Passing a ViewModel or is there a better way? Right now it returns about 500 records with the same data.
public class DimCustomersController : Controller
{
private AdventureWorks_MBDEV_DW2008Entities db = new AdventureWorks_MBDEV_DW2008Entities();
public ActionResult CustomersIndexVM()
{
List<DimCustomersIndexViewModel> CustomerList = new List<DimCustomersIndexViewModel>();
DimCustomersIndexViewModel CustomerItem = new DimCustomersIndexViewModel();
foreach (var m in db.DimCustomers.ToList())// cold do for loop up to count
{
CustomerItem.Title = m.Title;
CustomerItem.FirstName = m.FirstName;
CustomerItem.MiddleName = m.MiddleName;
CustomerItem.LastName = m.LastName;
CustomerItem.BirthDate = m.BirthDate;
CustomerItem.MaritalStatus = m.MaritalStatus;
CustomerItem.Suffix = m.Suffix;
CustomerItem.Gender = m.Gender;
CustomerItem.EmailAddress = m.EmailAddress;
CustomerItem.AddressLine1 = m.AddressLine1;
CustomerItem.AddressLine2 = m.AddressLine2;
CustomerItem.Phone = m.Phone;
//other columns go here
CustomerList.Add(CustomerItem);
}
return View("CustomersIndexVM", CustomerList);
}
This line needs to be inside the loop:
DimCustomersIndexViewModel CustomerItem = new DimCustomersIndexViewModel();
The reason is that you want a new view model for each customer, but instead you are currently creating only one view model and changing its properties. When you add it to the list, you are not adding a copy; you are adding the same view model you already added.
This code would work if DimCustomersIndexViewModel was a struct, because structs are just a bag of values that have no inherent identity and they are copied rather than referenced. (Technical comparison.) But it's a class (as it should be), with a unique identity, so you're adding a reference to the single view model into the list over and over. Customerlist[0] and CustomerList[1] and all the other items point to the same DimCustomersIndexViewModel object instance, whose properties are then overwritten and left equal to the very last customer.
By moving this line inside the loop, you are creating a separate DimCustomersIndexViewModel for each customer, each with its own set of properties, and CustomerList contains references to many different DimCustomersIndexViewModel object instances.
Once you have solid experience with this concept, a future step could be to use AutoMapper so that you don't have to maintain a list of all properties in your code here.
The problem is you add the same reference object during each iteration of your loop. That object never changes (you never new it up again), but you change the properties on the object. Then you add that object over and over. You need to new up that object each iteration of the loop.

Modifying item after addition to List does not update list

I have a member variable which is a list of reference types. In a method I create and item, add it to the list. The item is then updated point to another instance but the instance in the list does not get updated (his is in some unit test code). Example looks like
Item localItem = new Item(arg1, arg2);
this.itemList.Add(localItem);
// Do some testing and assertions
localItem = new Item(arg3, arg4); // This does not update the instance of
// localItem in this.ItemList
// Do some more testing and assertions
I can update my tests to fix this but it still caught me by surprise. I supose the List wants to keep the original instance passed through the Add method and cares not if the local variable which was used to pass it in now points to something else. Can anyone maybe confirm this understanding or explain it more clearly?
Ofcourse not. The localItem is a reference to the actual object (not the object itself). The list contains also a reference to this same object. If you assign another item to localItem it now points to another object but the list has still a reference to the old object.
If you want the object in the list to update automatically you must introduce a new object that holds a reference to the item and add this one to the list
public class ItemReference
{
public Item Item { get; set; }
}
Now you can create a local item like this
ItemReference itemRef = new ItemReference();
itemRef.Item = new Item(arg1, arg2);
this.itemReferenceList.Add(itemRef);
itemRef.Item = new Item(arg3, arg4);
Because the list now has a reference to the same (unchanged) itemRef it "sees" the new item as well.
The list has to be declared as
List<ItemReference> itemReferenceList;
When you add localItem to the list you add a reference to the object instance (assuming Item is a reference type aka a class) - when you subsequently create a new Item instance the result is a new reference (similar to a pointer) - if you want to update the list you have to remove the old item and add the new item - these are two totally different instances. Alternatively you can modify any properties on localItem and these will be reflected when you access the item through the list.

How to Insert Object Type in ListView?

I want to maintain both ID and Object Type in my ListView. I'm trying to do this:
lstView.Items.Insert(MyObject);
// can't do this, because it takes only Int and String
In my case, the ID is int, so that part is ok. But how to insert an object type and retrieve it in the Item_Selection changed event?
A ListView cannot add or insert an object directly like a ListBox or ComboBox, but instead you need to create a ListViewItem and set its Tag property.
The Tag property from Msdn
An Object that contains data about the control. The default is null.
Any type derived from the Object class can be assigned to this
property. If the Tag property is set through the Windows Forms
designer, only text can be assigned. A common use for the Tag
property is to store data that is closely associated with the control.
For example, if you have a control that displays information about a
customer, you might store a DataSet that contains the customer's order
history in that control's Tag property so the data can be accessed
quickly.
Example code:
MyObject myObj = new MyObject();
ListViewItem item = new ListViewItem();
item.Text = myObj.ToString(); // Or whatever display text you need
item.Tag = myObj;
// Setup other things like SubItems, Font, ...
listView.Items.Add(item);
When you need to get your object back from the ListView, you can cast the Tag property.
private void OnListViewItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) {
MyObject myObj = (MyObject)e.Item.Tag;
int id = myObj.Id;
// Can access other MyObject Members
}
Usually its easier to wrap the functionality into a helper method.
public static void CreateListViewItem(ListView listView, MyObject obj) {
ListViewItem item = new ListViewItem();
item.Tag = obj;
// Other requirements as needed
listView.Items.Add(item);
}
And you can do:
CreateListViewItem(listView, obj);
A ListView doesn't support a DataSource property like a lot of controls, so if you wish to data bind you will need to implement something a bit more custom.
Create new listviewitem object. use Tag property.
Quickest way around this is to keep a list of your object on the side:
List<MyObject> list = ... ; // my list
Generate a dictionary from the list with a string as the ID, or you can use the index to retrieve from the original list:
Dictionary<int,string> listBinder = new Dictionary<int,string>(
list.Select(i => new KeyValuePair<int,string>(i.ID, i.Name))
);
Bind or codebehind attaching the listview to the dictionary, then use the selected item to retrieve your object from your private list.

Categories

Resources