I have the following model in MVC:
public class ParentModel
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public IEnumerable<ChildModel> Children { get; set; }
}
When I want to display all of the children for the parent model I can do:
@Html.DisplayFor(m => m.Children)
I can then create a ChildModel.cshtml display template and the DisplayFor will automatically iterate over the list.
What if I want to create a custom template for IEnumerable?
@model IEnumerable<ChildModel>
<table>
<tr>
<th>Property 1</th>
<th>Property 2</th>
</tr>
...
</table>
How can I create a Display Template that has a model type of IEnumerable<ChildModel>
and then call @Html.DisplayFor(m => m.Children)
without it complaining about the model type being wrong?
In my question about not getting output from views, I actually have an example of how to template a model with a collection of child models and have them all render.
ASP.NET Display Templates - No output
Essentially, you need to create a model that subclasses
List<T>
orCollection<T>
and use this:In your template for the collection model to iterate and render the children. Each child needs to strongly-typed, so you may want to create your own model types for the items, too, and have templates for those.
So for the OP question:
Will make a strongly-typed model that's a collection that can be resolved to a template like any other.
This is in reply to Maslow's comment. This is my first ever contribution to SO, so I don't have enough reputation to comment - hence the reply as an answer.
You can set the 'TemplateHint' property in the ModelMetadataProvider. This would auto hookup any IEnumerable to a template you specify. I just tried it in my project. Code below -
You basically override the 'CreateMetadataFromPrototype' method of the 'CachedDataAnnotationsModelMetadataProvider' and register your derived type as the preferred ModelMetadataProvider.
In your template, you cannot directly access the ModelMetadata of the elements in your collection. I used the following code to access the ModelMetadata for the elements in my collection -
In my view, I simply call @Html.DisplayForModel() and the template gets loaded. There is no need to specify 'UIHint' on models.
I hope this was of some value.
Like this:
or like this:
where obviously you would have
~/Views/Shared/DisplayTemplates/YourTemplateName.cshtml
:The actual "valid answer" is -IMHO- not correctly answering the question. I think the OP is searching for a way to have a list template that triggers without specifying the UIHint.
Magic stuff almost does the job
Some magic loads the correct view for a specified type.
Some more magic loads the same view for a collection of a specified type.
There should be some magic that iterates the same view for a collection of a specified type.
Change the actual behavior?
Open your favorite disassembler. The magic occurs in
System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate
. As you can see, there are no extensibility points to change the behavior. Maybe a pull request to MVC can help...Go with the actual magic
I came up with something that works. Create a display template
~/Views/Shared/DisplayTemplates/MyModel.cshtml
.Declare the model as type
object
.If the object is a collection, iterate and render the template again. If it's not a collection, then show the object.
Now
DisplayFor
works withoutUIHint
.