i have this entity called BlogArticle which has a property called
public virtual ICollection<BlogComment> BlogComments { get; set; }
what i wanna do is access those properties of the blogcomments in my view but since it is in a ICollection i cannot itterate through it. (.count() does work.)
Any suggestions on this matter?
cheers.
You can enumerate the collection by using a foreach loop. If you need random access to the elements of the collection you can use the ToList() extension method. That will create a new list containing all the elements of the collection.
foreach (var blogComment in blogArticle.BlogComments) {
// Access sequentially from first to last.
}
or
var blogComments = blogArticle.BlogComments.ToList();
for (var i = 0; i < blogComments.Count; ++i) {
var blogComment = blogComments[i]; // Access by index - can be done in any order.
}
ICollection is an interface, so it depends on how you are initializing this object i.e.
ICollection<BlogComment> BlogComments = new List<BlogComment>();
Would allow you to do...
BlogComments.Count;
For future reference being that the question is a bit old... I'm surprised that no one mentioned this before, but if you do not want to do the cast in either the view model or the view itself you could do:
#for(int i = 0; i < model.BlogComments.Count; i++)
{
#Html.DisplayFor(model => model.BlogComments.ElementAt(i));
}
EDIT: I will add that this is only a useful strategy for displaying data (edited the example to show this), not a useful strategy inside of a form where you want to have the values posted back to your action method when used in HTML helpers like EditorFor. The name property of input is not formed in a way that will allow the model binder to bind these values back to the collection. You would either have to write the name out by hand (not robust) have some sort of intermediary collection type with the index operator like IList that you keep in sync with the ICollection.
Related
I have a ObservableCollection and I want to display only 10 items of it in the ListView. How must the Filter look like?
CollectionView altView = (CollectionView)CollectionViewSource.GetDefaultView(alteParkingListe.ItemsSource);
altView.Filter += //Show only 10 Items
The signature of the the Filter property is as follows:
public virtual Predicate<object> Filter { get; set; }
Consequently, you need to supply a Predicate<object> which is a funtion that takes an argument of type object and returns a bool. The argument passed in is an item of the underlying collection. The filter predicate is called for each item. The return value indicates whether the item is preserved (true) or filtered out (false) of the view.
As you can see, the filter does not know anything about the underlying collection itself, only each item individually. Hence, there is no direct way of doing this with a filter.
Of course you can do dirty tricks like keeping the count of filtered items like this:
var itemsCount = 0;
altView.Filter = obj => ++itemsCount <= 10;
However, this is not a good solution and you need to ensure that itemsCount is reset each time.
Now for what you should do instead: Simply create another collection property and assign a filtered variant of your main collection, no collection view and no dirty tricks involved. Filtering can be done using Linq's Take method:
FilteredItemsCollection = AllItemsCollection.Take(10);
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
}
I got a class called BG which has a property called Name Code.
I instantiate an object called bgList.
Now I am trying to get all the Code of the objects which have their 'Crop' property set to cropName.
I would like to convert the following working code to linq but for the life of me am unable to do that - am quite sure that I am missing something:
List<string> breedingGroupsAndRoles = new List<string>();
for (int i = 0; i < bgList.Count; i++)
{
if (bgList[i].Crop == cropName)
breedingGroupsAndRoles.Add(bgList.[i].Code);
}
The closest I came was this but it only nets me the first item:
breedingGroupsAndRoles.Add(bgrList.Find(c => c.Crop == cropName).Role);
List<string> breedingGroupsAndRoles = bgList
.Where(bg => bg.Crop == cropName)
.Select(bg => bg.Code)
.ToList();
Just for the sake of completeness, the Find method you tried calling on bgList is not part of LINQ, it's a member of the generic List class itself. It only returns the first element matched by the predicate you provide, which is why you were only getting one result. You probably wanted the FindAll method, which returns a list of all matching elements:
List<BG> breedingGroups = bgList.FindAll(c => c.Crop == cropName);
Note that this produces a list of matching BG instances rather than just their Role properties. Depending on how you're processing the results this may be sufficient, otherwise you'll still need LINQ or a loop and a second list to extract the Role values. In any case, an all-LINQ solution such #Tim Schmelter's is likely the better way to go.
IEnumerable<ReportFavorite> list = reportService.GetReportFavorites(userId);
ddlReportFavorite.Items.Add()
I don't know how to add the lists to the dropdown using Linq. Thanks.
You an use AddRange method:
var list = reportService.GetReportFavorites(userId);
ddlReportFavorite.Items.AddRange(list.ToArray());
Depending on the dropdown control you are using, either of these could work:
If it allows its Items to be set to an IEnumerabe<ReportFavourite>:
ddlReportFavorite.Items = reportService.GetReportFavorites(userId);
If Items implements the AddRange method:
ddlReportFavorite.Items.AddRange(reportService.GetReportFavorites(userId));
Or, if these fail
foreach(var reportFavourite in reportService.GetReportFavorites(userId))
ddlReportFavorite.Items.Add(reportFavourite);
Neither of these methods is really "using LINQ", because LINQ is not a good tool to do this. LINQ is meant to be side-effect free.
Edit:
Your comment suggests that you are using a System.Web.UI.WebControls.DropDownList. In this case, the Items collection only accepts instances ListItem, so you need to create these from your ReportFavourites. Try
foreach(var listItem in reportService.GetReportFavorites(userId)
.Select(r => new ListItem(r.Id, r.Name))
ddlReportFavorite.Items.Add(listItem);
Here, I assume the combo box should display ReportFavourite.Name and have a value of ReportFavourite.Id. Use your own properties, of course
Or if you've already checked the data's integrity in the method, you could just simply say:
ddlReportFavorite.Items.AddRange(reportService.GetReportFavorites(userId));
Previously I put as IEnumerable. Now I changed to IList. It is working fine now. Thanks to all.
int userId = workContext.CurrentUser.UserID;
var reportFavoriteList = reportService.GetReportFavorites(userId);
int count = reportFavoriteList.Count;
for (int i = 0; i < count; i++)
{
ddlReportFavorite.Items.Add(reportFavoriteList[i].FavoriteName);
}
Since ddlReprotFavorite is an UI control and itsItemsproperty represent a set of controls as well you can not add directly your business entities instead of use DataSource property which automatically create Items collection from the underlying business entities.
IEnumerable<ReportFavorite> list = reportService.GetReportFavorites(userId);
ddlReportFavorite.DataSource = list;
The IEnumerable<T> is extended by the method Union<T> which unions two IEnumerable<T>'s. This is the more pretty way, without casting it ToList().
var reportFavoriteList = reportService.GetReportFavorites(userId);
ddlReportFavorite.Items = ddlReportFavorite.Items.Union(reportFavoriteList);
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";