views:

876

answers:

2

Hi,

I've got a couple of questions about the naming convention for the DisplayTemplates and EditorTemplates in MVC 2.

If for example I have a customer object with a child list of account how do I:

  • Create a display template for the list of accounts, what is the file called?

  • When I'm doing a foreach( var c in Model.Accounts ) how do I call a display temple while in the foreach loop? When I do Html.DisplayFor( x => x ) inside the foreach x is the model and not in this case c.

Thanks in advance.

+1  A: 

Brad Wilsons blog here http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html has an example about DisplayTemplates and EditorTemplates for Custom Objects, and it discusses issues which may be helpful in resolving your question.

Regarding your first question, it is important that your template resides in a folder which the system looks for matching names in, e.g.

 ~/Views/ControllerName/DisplayTemplates/TemplateName.aspx & .ascx
 ~/Views/Shared/DisplayTemplates/TemplateName.aspx & .ascx 

(Replace DisplayTemplates with EditorTemplates for the search paths for editor templates.)

The following template names are tried in order:

  • TemplateHint from ModelMetadata
  • DataTypeName from ModelMetadata
  • The name of the type (see notes below)
  • If the object is not complex: “String”
  • If the object is complex and an interface: “Object”
  • If the object is complex and not an interface: Recurse through the inheritance hiearchy for the type, trying every type name

I'm not sure about an answer for your second question. Is it right to assume that var c is actually effectively Account c? And when you are writing Html.DisplayFor(x => x) you might as well be writing Html.DisplayModelFor(c => c) ? Or do you want to have `Html.DisplayFor(x => x.AccountName), for instance?

Alex White
Hi, thanks for the link it doesn't quite answer all my questions though. Say for example I have a Customer with a Child List of Orders. At the moment if I want to show a list of orders I've created a partial view of IEnumberable<order> and loop around each object creating a table. If I wanted to use this I would say something link Html.RenderPartial("OrdersTable",Model.Orders) but instead of using this I would like to say Html.DisplayFor( x => x.Orders) and it finds a display template but I dont know what to call the display template for a list.
Simon G
I've been banging my head against this one for a while. I didn't realise that the search paths were important. Will edit your post to make this clear.
Dead account
+2  A: 

Yeah, this is one of my favorite features, but it's a bit confusing for some things.

So, creating a template for any class, the name is based on the type's Name property, so for example if you do a <%= model.GetType().Name %> in your view, you can see what I mean. As an example, if your list of accounts is an IList, then the call to .Name on the type would return List1. That's a legal file name, so if you put List1.ascx in your DisplayTemplates folder, it'll find it and use it. from what I can tell, it won't traverse the class hierarchy, though, so for example if you put an IEnumerable`1.ascx file in there, it won't find it.

To display in a loop, you need to pass in the item variable into the lambda, so in your example:

<% foreach (var c in Accounts){ %>
      <li><%= Html.DisplayFor(x => c) %></li>
<%}%>

Hope that helps. Paul

Paul
Thanks for the answer works fantastic. Just another question if I have two separate objects with different child lists say accounts and people both will have the object name List`1 how do you differentiate between the two? Or do you have to use UIHint attributes?
Simon G
yep, both will have the same. I think the UIHint will work (haven't tried) but what you can also do is have the list template be generic (say, based on IEnumerable, non-generic) and then have it call DisplayFor inside *its* list, and then the list items will each have their properly typed template. You can also, iirc, pass in an explicit template name as a string in one of the overloads.
Paul