Why doesn't my DisplayFor loop into my IEnumerable <DateTime>?

I have this line in my view

@(Html.DisplayFor(m => m.DaysOfWeek, "_CourseTableDayOfWeek")) 

where m.DaysOfWeek is IEnumerable<DateTime> .

Contents of _CourseTableDayOfWeek.cshtml:

 @model DateTime @{ ViewBag.Title = "CourseTableDayOfWeek"; } <th> @System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.DayNames[(int) Model.DayOfWeek] <span class="dateString">Model.ToString("G")</span> </th> 

And I get the following error:

The model element passed to the dictionary is of type " System.Collections.Generic.List`1[System.DateTime] ", but this dictionary requires a model element of type " System.DateTime ".

If I refer to the following message:

stack overflow

DisplayFor should loop around on IEnumerable and display a template for each element, right?

+18
view asp.net-mvc-3
Dec 30 '11 at 11:06
source share
4 answers

It does not loop because you specified the name for the display template as the second argument to the DisplayFor helper ( _CourseTableDayOfWeek ).

It loops only when you rely on agreements, i.e.

 @Html.DisplayFor(m => m.DaysOfWeek) 

and then inside ~/Views/Shared/DisplayTemplates/DateTime.cshtml :

 @model DateTime @{ ViewBag.Title = "CourseTableDayOfWeek"; } <th> @System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.DayNames[(int) Model.DayOfWeek] <span class="dateString">Model.ToString("G")</span> </th> 

After you specify your own name for the display template (either as the second argument to the DisplayFor helper element, or as the [UIHint] attribute), it will no longer loop over the properties of the collection, and the template will simply be passed as IEnumerable<T> as model,

This is confusing, but it is. I don't like that either.

+24
Dec 30 '11 at 13:34
source share

This seems like a mistake. The Html Helper classes expand easily, although by looking at the MVC source and looking for an error, I refused and simply used the assumption that the templates work for a single element, so I wrote the HtmlHelper extension that completes it for you. I pulled out a lambda expression for my simplicity, but you can easily get back to that. This example is for a list of strings only.

  public static class DisplayTextListExtension { public static MvcHtmlString DisplayForList<TModel>(this HtmlHelper<TModel> html, IEnumerable<string> model, string templateName) { var tempResult = new StringBuilder(); foreach (var item in model) { tempResult.Append(html.DisplayFor(m => item, templateName)); } return MvcHtmlString.Create(tempResult.ToString()); } } 

Then the actual use is as follows:

  @Html.DisplayForList(Model.Organizations, "infoBtn") 
0
Nov 01 '13 at 21:37
source share

A small tweak that allows this Dan solution to be a little more general:

 public static class DisplayTextListExtension { public static MvcHtmlString DisplayForList<TModel, EModel>(this HtmlHelper<TModel> html, IEnumerable<EModel> model, string templateName) { var tempResult = new StringBuilder(); foreach (var item in model) { tempResult.Append(html.DisplayFor(m => item, templateName)); } return MvcHtmlString.Create(tempResult.ToString()); } } 
0
Jan 10 '19 at 12:59
source share

Use FilterUIHint instead of the regular UIHint in the IEnumerable<T> property.

 public class MyModel { [FilterUIHint("_CourseTableDayOfWeek")] public IEnumerable<DateTime> DaysOfWeek { get; set; } } 

Nothing else is needed.

 @Html.DisplayFor(m => m.DaysOfWeek) 

Now the "_CourseTableDayOfWeek" EditorTemplate is displayed for each DateTime in DaysOfWeek .

-one
Oct 07 '14 at 2:05
source share



All Articles