MVC Custom View Editor Templates
When creating MVC3 razor website it is often necessary to apply custom templates on classes or properties within the objects to be displayed seamlessly throughout your application. There is number of ways to apply custom templates, one of them is to create folders in ~/Shared/DisplayTemplates/, ~/Shared/EditorTemplates/ and create partial views based on model objects we want to style. Lets start with creating basic class structure that we will work on:
public partial class Client { public int ClientId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public Address HomeAddress { get; set; } [UIHint("bool")] public bool IsApproved { get; set; } [UIHint("Enum")] public Role Role { get; set; } } public enum Role { Admin, PM, Employee } public partial class Address { public string Street { get; set; } public string City { get; set; } public string Country { get; set; } }
As you can see there are two properties marked with the UIHint attribute. This is one of the ways to map properties with the templates.
When displaying form we can also specify template name if we want to apply template only for selected pages.
<div class="editor-field"> @Html.EditorFor(model => model.IsApproved) @Html.ValidationMessageFor(model => model.IsApproved) </div> <div class="editor-field"> @Html.EditorFor(model => model.Role) @Html.ValidationMessageFor(model => model.Role) </div>
This is similar when creating display templates. We can also mix the ways of assigning templates by choosing the properties attributes and template names if required.
<div class="display-field"> @Html.DisplayFor(model => model.IsApproved) </div> <div class="display-label"> Role</div> <div class="display-field"> @Html.DisplayFor(model => model.Role, "MyRole") </div>
Our editor template implementation is quite simple. For each enum value in our Role class we create list item to be shown in drop down list. We also need to ensure that we give it a proper name Role.cshtml in order for the view engine to be able to correctly identify our template.
@model Models.classes.Role <select id="Role" name="Role"> @foreach (Models.classes.Role value in Enum.GetValues(typeof(Models.classes.Role))) { <option value="@value" @(Model == value ? "selected=\"selected\"" : "")>@value </option> } </select>
Display template contains the code below. We simply mark in red the current Role value. Of course it’s only a quick sample.
@model Models.classes.Role @foreach (Models.classes.Role value in Enum.GetValues(typeof(Models.classes.Role))) { if (Model == value) { <p><b style="color:Red;">@value.ToString()</b></p>; } else { <p>@value.ToString()</p> } }
If we want to override the templates located in the Shared folder, we can create folder in the view (~/Views/
We can also create generic templates to override default rendering of build-in types like bool? We apply it also by giving the attribute to the property of our object. Following implementation displays in bold one of the 3 possible object states.
@model bool? @if (ViewData.ModelMetadata.IsNullableValueType && Model == null) { @:True False <b>Not Set</b> } else if (Model.Value) { @:<b>True</b> False Not Set } else { @:True <b>False</b> Not Set }
MVC framework gives us a chance to override and customize pretty much of everything. We can also create our own View Engine and change the way of model binding etc.
I have included project sample below for you tests.
MVC-Custom-display-templates