0

I have a search page that display a search result. The search result is a list of persons that matched the specific search. I'm iterating through this list displaying them in a table. As headers for this table I want the DisplayName from the model. If I don't inherit IEnumerable I wouldn't be able to iterate through the list. I'm new at this MVC thing =)

I iterate through the result like this:

<% foreach (var item in Person) { %> 
   <%: item.surname %>
<% } %>

But how do I print the "DisplayName" of an attribute without iterating through the whole list? I would just like to do:

<%: Html.LabelFor(m => m.surname) %>

If it's any help I inherit an IEnumerable at the top of the page:

<%@ Page Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>" %>  

Edit
I want to display "Your surname" but I don't know how to access it from the view.

[DisplayName("Your surname")]
public object surname { get; set; }  

Here's a very similar question that hasn't been answered either: Can I use LabelFor() when the page inherits from IEnumerable<T>?

Community
  • 1
  • 1
Niklas
  • 13,005
  • 23
  • 79
  • 119
  • OK, so you only want to display the first record, or you want it to be easier to display all of the surnames on the items in the model? I'm a little confused.... – Brian Mains May 24 '11 at 16:00
  • No, I don't want nothing to do with the records. I want to display the "DisplayName" have set for the attribute "surname" in the model. I've updated my question a bit. – Niklas May 25 '11 at 06:57
  • But the IENumerable<> you send does not have a "surname", it is not a Person object, it is a IENumerable<> of persons. If you do not want anything to do with the items you should reconsider your design. – bastijn May 25 '11 at 07:15

3 Answers3

3

If you only need to display specifics of one person; you should consider sending only one person to the view instead of a complete list of persons. In that case

Model.Surname

would work just like that. So instead of:

Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"

do

Inherits="System.Web.Mvc.ViewPage<RegistryTest.Models.Person>"

In this case a single person is loaded into your Model and Model.Property works fine. If you want an IENumerable<>, think about what that means. You are sending a list of persons, so the only thing in your "Model" is a IENumerable<> of persons. There is no way that the view can know what you want if you call Model.Property, since in the Model there are multiple Objects and the view doesn't know which Object you want to get the Property from.

Bottom line, if you want to call Model.Property (Model.surname) but also want to send an IENumerable you are having a design flaw. If you send a list you should want to do something with the complete list (iterate through and do something with the contents). If you just want to do something with one person in that list, re-design your view/controller and send that single person; then you can use Model.Property.

//EDIT BASED UPON COMMENTS As I see it now you either want to do one of those two things (I do not know which):

  1. Show the records of an item in your list in a table and put the DisplayName of the current object shown in the table in the header.
  2. Show all items of the list in your table and put some sort of DisplayName in the header. This makes less sence but it could be that you mean to name your list.

Situation 1 This is working as the rest of your code? The following would work just fine.

<% foreach (var item in Model) { %> 
   <table>
      <th>item.DisplayName</th>
      <tr>
         <td>item.Property1</td>
         <td>item.Property2</td>
      </tr>
   </table>
<% } %>

Situation 2 If you want a DisplayName of the list (??) you should create a ViewModel containing the IENumerable of Persons and a public string ListName. Now you can do something like:

<table>
  <th>Model.ListName</th>
  <% foreach (var item in Model) { %>           
      <tr>
         <td>item.Property1</td>
         <td>item.Property2</td>
      </tr>
  <% } %>
</table>

this would create a table with the name of your List (given in the ViewModel) as header and as items in the table you have your persons.

Design problem? However, I would love to see you write some more information in your question above. Give us some more information on what you want to do. Do you want to show records of each Person in the list one-by-one? In that case I would recommend you create a Partial View where you put your table. Then you would get something like:

<% foreach (var item in Model) { %>     
   <% Html.RenderPartial("TablePerson",item); %>
<% } %> 

tableperson.ascx:

...
Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"
...
<table>
   <th>Model.DisplayName</th>
   <tr>
      <td>Model.Property1</td>
      <td>Model.Property2</td>
   </tr>
</table>

So, we need more information I'm afraid :)

bastijn
  • 5,841
  • 5
  • 27
  • 43
  • I have a search page that display a search result. The search result is a list of persons that matched the specific search. I'm iterating through this list displaying them in a table. As headers for this table I want the DisplayName from the model. If I don't inherit IEnumerable I wouldn't be able to iterate through the list. I'm new at this MVC thing =) – Niklas May 25 '11 at 07:49
  • Conclusion: First I want to display the "DisplayName" in the headers of the table then iterate through the list displaying the search result. If there's a more correct way to do this I'd like to learn it! – Niklas May 25 '11 at 07:54
  • What displayname? The displayname of the list? IENumerables do not have DisplayNames. If you want to see your list as an object and give it a name you should create a custom viewmodel and give it a list and a DisplayName. That would be the way to go. – bastijn May 25 '11 at 08:24
  • No, the displayname of surname, or in your case Property1. When you have an edit page you can write like this: `<%: Html.TextBoxFor(model => model.surname) %>` and `<%: Html.LabelFor(model => model.surname) %>`. With this I would get a label saying "Your surname" and a textbox for surname. This is the label I want in my example too. I appreciate your the time you're putting in to help me =) – Niklas May 25 '11 at 08:55
  • So what is wrong with situation one described above? Is DisplayName an attribute of the Person object or not? If so, situation one works :?. If not, what is it an attribute of, certainly not of the standard IENumerable you are sending ? Can you maybe once more, in your original question maybe, describe in detail the page you want to create including all data you want to visualize on which spot? – bastijn May 25 '11 at 11:56
  • In your first example it looks like you take the Displayname of "item" which in my case is a `Person`. You also display this for every item in the list when I only need it one time, before looping through the list. I also want the display name of `item.Property1` and not just item. Take a look at "NerdDinner_v1, page 60", there's a table there that works exactly like I want it to. Anyway, I really appreciate your effort here, but this would probably take too long to explain =/ – Niklas May 25 '11 at 12:48
  • The table headers on page 60 of NerdDinner are just hardcoded :). It is a header, not dynamic at all. If you need it once, before looping through the list, why do you need to retrieve it from a record? If you want it to be a dynamic header, create a ViewModel (search for it on google) and let it contain your list and dynamic table headers. Then use this ViewModel as your Model in the view. I think you are missing some general concept somewhere, your question is hard to understand, sorry :(. – bastijn May 25 '11 at 13:39
  • Yes, a ViewModel could be exactly what I need. Because I both need to pass a list of Persons to the View as well as the properties (surname, lastname etc.) of the class Person. I don't want the headers of the table to be hardcoded, I want to use their DisplayName from the Person class. This way I'd only have to change the displayname in one place. – Niklas May 26 '11 at 08:19
  • I created a PersonViewModel which takes a Person and a List `IENumerable`. So I can use this for the label `<%: Html.LabelFor(m => m.Person.surname) %>` and this for the iteration of data `<% foreach (var item in Model.List) { %> <%: item.surname %> <% } %>` – Niklas May 26 '11 at 09:33
  • Oke, if it solves your problem. However, you should ask yourself: what is the meaning of this separate person? Why do you need that person for the LabelFor method? what is so special about this person in the list? I still don't get it and find it a rather strange design, but if it solves your problem; well done i guess :). Happy to help! – bastijn May 26 '11 at 09:37
  • It's not a separate person I'm referencing, it's the actual class `Person`. This is a very similar problem: http://stackoverflow.com/questions/4479032/read-dataannotations-from-a-collection-of-models-in-an-mcv2-view . It also uses the First() the way I did, before I created the PersonViewModel. – Niklas May 26 '11 at 10:47
0

If it's a collection with every entry having the same surname then try model[0].surname or model.ToList().First().surname

You don't need ToList() if its a List<T> already. Then it would be just model.First()

Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
0

You are specifying that the page model is IEnumerable, and you say you would like to print a property of an element. Since you have a list of elements, you need to specify which of the elements you would like to retrieve the property from.

I you want a specific index in the list you will need to convert the IEnumerable collection to IList (ToList()), depending on the criteria, you may also be able to find the required element using something like a LINQ Single() operation.

Otherwise you could select the property from all the element in the list using Model.Select(m => m.PropertyName) which will give you a list of just this property, and then concatenate this list to a single string.

DEHAAS
  • 1,294
  • 11
  • 17
  • If I do `Model.First().surname` I get the actual surname and not the label. If I do `Model.Select(m => m.surname)` it prints `System.Linq.Enumerable+WhereSelectListIterator'2[RegistryTest.Models.Person,System.String]` – Niklas May 25 '11 at 07:01