24

I have a view with a strongly-typed model associated with it

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
                  Inherits="System.Web.Mvc.ViewPage<SomeNamespace.SomeViewModel>" %>

The SomeViewModel looks like this

class SomeViewModel
{
    public IEnumerable<Foo> Foos {get; set;}
}

and say Foo is

class Foo
{
   public string Bar {get; set;}
}

and in the view

<% foreach (var item in Model.Foos) { %>
    <tr>
        <td>
            <%= Html.LabelFor(f => f.Bar) %>
        </td>

I'm not sure how to display Bar property in item using Html.LabelFor()

Can someone help me with this?

Thanks,

Professor Chaos
  • 8,470
  • 7
  • 34
  • 53
  • Are you getting an error with that code? – AndrewC Sep 16 '11 at 13:34
  • @AndyC I don't know how to get at Bar for the loop variable `item`. f => f.[No Bar here. only Foos]` – Professor Chaos Sep 16 '11 at 13:40
  • @TheOtherGuy, most examples i've seen have hard coded the labels as table headers and then done the for each after. Are you displaying yours in a table? is there a reason you need the label in your foreach (it will just constantly repeat your label for every row) – Manatherin Sep 16 '11 at 13:47
  • @Manatherin I have a collection of Foo objects and i'm trying to display the Bar property for each Foo in each table row. – Professor Chaos Sep 16 '11 at 13:52

6 Answers6

48

Do this instead:

<% foreach (var item in Model.Foos) { %>      
<tr>          
    <td>              
        <%= Html.LabelFor(f => item.Bar) %>          
    </td>
<% } %>

Instead of f => f.Bar do f => item.Bar, where item is the name of the variable in your foreach loop.

Here is the much more beautiful razor syntax :)

@foreach( var item in Model.Foos ) {
<tr>
    <td>
        @Html.LabelFor(f => item.Bar)
    </td>
    <td>
        @Html.DisplayFor(f => item.Bar)
    </td>
</tr>
}
Dismissile
  • 31,646
  • 36
  • 169
  • 255
  • 1
    That is awesome. Not sure the how and why though. An explanation of the need for the mismatch would be helpful for the noobs. – Snekse May 15 '14 at 20:43
  • Related question: How do I do this and have `TextBoxFor` produce a different ID for each item so I can update properly? – Snekse May 15 '14 at 20:47
  • Im not sure why this isnt the accepted answer. – Donald Sep 22 '21 at 14:20
2

have you tried

<% for (var i=0; i<Model.Foos.Count();i++) { %> 
    <tr> 
        <td> 
            <%= Html.LabelFor(f => f.Foos[i].Bar) %> 
        </td> 

The LabelFor extension uses a lamda expression to go from your Model object to the selected property, consider f a substituion variable for your model. So you need a way to get from your model to your chosen property. You are telling LabelFor, create a local variable called f and assign it with the value of your model. then use the bit after the => to determine the target property.

If you are desperate to use the foreach, you would have to have a way of translating item back to a property of the original model, (e.g. for an array as Gledrius said x=>x.Foos[Model.Foos.IndexOf(foo)])

failing that if you just want the text value

use '<%= item %>' instead of the whole labelfor or if you have ASP.NET 4 and MVC2 or better use <%: item %> for that HTML encoding goodness

Bob Vale
  • 17,579
  • 40
  • 48
2

You could also just write a custom extension that's not tied directly to the Model of the page.

   public static MvcHtmlString LabelForItem<T, V>(this HtmlHelper html, T obj, Expression<Func<T, V>> expression) 
   {
       Func<T,V> func = expression.Compile();
       V val = func(obj);
       return html.Label(val.ToString());
   }

And you'd use it, like this:

@foreach (Foo foo in Model)
{
    <p>
       @(Html.LabelForItem<Foo, string>(foo, f => f.Name))
    </p>
}
mdm20
  • 4,415
  • 2
  • 20
  • 24
0

From here, looks like you need to specify the DisplayName on the property:

[DisplayName("My Bar")]
public string Bar { get; set; }
Community
  • 1
  • 1
SwDevMan81
  • 47,539
  • 21
  • 146
  • 180
0

if Foos would be list, it would look like this:

Html.LabelFor(x=>x.Foos[Model.Foos.IndexOf(item)])
Giedrius
  • 8,268
  • 6
  • 48
  • 87
0

You are iterating over your Foo's but not using the item variable at all.

AndrewC
  • 6,590
  • 13
  • 41
  • 69