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,850
  • 8
  • 38
  • 54
  • 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
  • 32,564
  • 38
  • 174
  • 263
  • 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
  • 18,094
  • 1
  • 42
  • 49
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,475
  • 2
  • 22
  • 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
  • 48,814
  • 22
  • 151
  • 184
0

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

Html.LabelFor(x=>x.Foos[Model.Foos.IndexOf(item)])
Giedrius
  • 8,430
  • 6
  • 50
  • 91
0

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

AndrewC
  • 6,680
  • 13
  • 43
  • 71