简体   繁体   中英

How do I create a MVC Razor template for DisplayFor()

I have a couple of properties in my view model that are display-only but I need to retrieve their values using jQuery to perform a calculation on the page. The standard Html.DisplayFor() method just writes their value to the page. I want to create a razor template that will allow me to render each element as:

<span id="ElementsId">Element's value</span>

I know I can specify a template in Html.DisplayFor() to use a particular template for rendering the property but within that template how do I identify the id attribute to write into the span tag?

@Html.DisplayFor(model => model.Element, "MyTemplate");

OK, I found it and it's actually very simple. In my Views\\Shared\\DisplayTemplates folder I have Reading.cshtml containing the following:

@model System.Int32
<span id="@ViewData.ModelMetadata.PropertyName">@Model</span>

This renders the correct tag using the name of the property as the id attribute and the value of the property as the contents:

<span id="Reading">1234</span>

In the view file this can be called using the following:

@Html.DisplayFor(model => model.Reading, "Reading")

Or if the model property is decorated with UIHint("Reading") then the template name can be left out of the call to DisplayFor() and it will still render using the template:

@Html.DisplayFor(model => model.Reading)

This should work equally well with custom editor templates.

I read many SO posts about defining template for @Html.DisplayFor for Boolean property but I couldn't clearly understand them. Your question is closed to this and after grasping it, I decided to add a new answer including all steps needed for implementing that. It might be helpful for other people.

1. Creating a template

At first, you need to add a Partial View in path below (the path is very important):

Views/Shared/DisplayTemplates/

For example, I created a Partial View that named _ElementTemplate and Fill it like this:

<span>
    @(@Model ? "Yes" : "No")
</span>

2. Adding UIHint to the Model

To make a connection between your property and template , you should add UIHint attribute like below in your model class:

[UIHint("_YesOrNoTemplate")]
public bool MyProperty { get; set; }

3. Using @Html.DisplayNameFor in View

In every view that you need this property, you can use code below:

<div>
    @Html.DisplayFor(modelItem => item.MyProperty)
</div>

Output

The code above is rendered to code below in my example ( if (MyProperty == true) ):

<div>
    <span>
        Yes
    </span>
</div>

Setting attributes

For setting id or other html attributes you can use ModelMetadata like this:

<span id="@ViewData.ModelMetadata.PropertyName">
    @(@Model ? "Yes" : "No")
</span>

Output with attribute

<div id="MyProperty">
    <span>
        Yes
    </span>
</div>

您可以将此id视图模型的一部分并在显示模板中使用它:

<span id="@Model.Id">@Html.DisplayFor(x => x.Value)</span>

一篇文章解释了 Razor 中的Templates (显示 + 编辑器)以及UIHint属性。

I had exactly the same issue as the original post.

Not sure the last comment is valid. It would make the HTML id attribute a run-time value and therefore cannot be referenced with a design time name.

I used the overload of DisplayFor which allows you to add new objects onto the data dictionary (ViewBag)

My model is a C# object called Project with various properties. In my view I have this:

@Html.DisplayFor(model => model.ProjectName, "StringDisplaySetHtmlID", new { HtmlID = "project-name" })

This is using a custom template called StringDisplaySetHtmlID and the last parameter adds a key value pair to the Viewbag.

My template file looks like this:

@model string
<span class = "display-field" id = "@(ViewBag.HtmlID)">@Model</span> 

I'm also setting a class here for styling purposes. I've used the key name HtmlID rather than just ID to avoid a potential common naming collision.

Now in my javascript I can pick up the span's content using the following jquery:

var projectName = $('#project-name').text()

The best way to build a display template that will output the following:

<span id="ElementsId">Element's value</span>

Would be this:

<span id="@Html.IdForModel()">@Html.DisplayTextFor(m => m)</span>

These helpers may not have existed when this question was first posted, but this builds on David's answer in two ways:

  1. Using @Html.DisplayTextFor(m => m) instead of @Model will still utilize data annotations while rendering the value instead of just essentially running ToString() on it.
  2. Using @Html.IdForModel() instead of @ViewData.ModelMetadata.PropertyName would be preferable in cases where the model is nested or repeated, and the ID is not going to simply be the property name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM