Templating Html.DisplayFor() in ASP.NET MVC 2

devuxer picture devuxer · Feb 7, 2010 · Viewed 9.7k times · Source

It appears that if you just use Html.DisplayFor(model => model) with no templates for a Details view, the resulting markup will look something like this:

<div class="display-label">first name</div>
<div class="display-field">Dan</div>
<div class="display-label">last name</div>
<div class="display-field">M</div>
<div class="display-label">email</div>
<div class="display-field">[email protected]</div>

This has a fair degree of flexibility. If you create CSS classes for display-label and display-field, you can do quite a bit, but what if I wanted to change it to something like this?

<p>
  <span class="display-label">first name</span>:
  <span class="display-field">Dan</span>
</p>
<p>
  <span class="display-label">last name</span>:
  <span class="display-field">M</span>
</p>
<p>
  <span class="display-label">email</span>:
  <span class="display-field">[email protected]</span>
</p>

Note that now the attribute-value pairs now appear side-by-side (instead of on separate lines) and there is a colon after each attribute.

Is there any way to create a custom template that will be repeated for each attribute-value pair when a details view is scaffolded?

I'm not talking about a specific template for a model (e.g., a Person template) or a template for a particular property (e.g., an EmailAddress template). I want something that just lets me describe how an attribute-value pair looks, then DispalyFor() should automatically repeat that template for each property in my model or view model.

Answer

mnemosyn picture mnemosyn · Feb 7, 2010

How about overriding the Object template, e.g.

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <% if (ViewData.TemplateInfo.TemplateDepth > 3) { %>
        <%= ViewData.ModelMetadata.SimpleDisplayText %>
    <% } else { %>
        <table>
        <% foreach (ModelMetadata prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) { %>
            <% if (prop.HideSurroundingHtml) { %>
                <%= Html.Display(prop.PropertyName) %>
            <% } else { %>
                <tr>
                    <td>
                        <div class="display-label" style="text-align: right;">
                            <%= Html.Label(prop.PropertyName) %>
                        </div>
                    </td>
                    <td>
                        <div class="display-field">
                            <%= Html.Display(prop.PropertyName) %>
                            <%= Html.ValidationMessage(prop.PropertyName, "*") %>
                        </div>
                    </td>
                </tr>
            <% } %>
        <% } %>
        </table>
    <% } %>

See http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html