English 中文(简体)
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 ViewsSharedDisplayTemplates 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>

You could make this id part of the view model and use it in the display template:

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

There s an article explaining the Templates (Display + Editor) in Razor, and also the UIHint attribute.

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.




相关问题
WebForms and ASP.NET MVC co-existence

I am trying to make a WebForms project and ASP.NET MVC per this question. One of the things I ve done to make that happen is that I added a namespaces node to the WebForms web.config: <pages ...

Post back complex object from client side

I m using ASP.NET MVC and Entity Framework. I m going to pass a complex entity to the client side and allow the user to modify it, and post it back to the controller. But I don t know how to do that ...

Create an incremental placeholder in NHaml

What I want to reach is a way to add a script and style placeholder in my master. They will include my initial site.css and jquery.js files. Each haml page or partial can then add their own required ...

asp.net mvc automapper parsing

let s say we have something like this public class Person { public string Name {get; set;} public Country Country {get; set;} } public class PersonViewModel { public Person Person {get; ...

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor)...

ASP.NET MVC: How should it work with subversion?

So, I have an asp.net mvc app that is being worked on by multiple developers in differing capacities. This is our first time working on a mvc app and my first time working with .NET. Our app does not ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

热门标签