ASP.NET MVC 的 DisplayTemplates 和 EditorTemplates 命名规则约定

14

我有几个关于MVC 2中DisplayTemplates和EditorTemplates的命名约定的问题。

比如说,我有一个客户对象和一个子帐户列表,那我应该怎么做:

  • 创建一个用于显示账户列表的模板,文件应该叫什么?

  • 当我使用 foreach(var c in Model.Accounts) 时,如何在循环中调用一个显示模板?当我在foreach中使用 Html.DisplayFor(x => x) 时,x 是模型,而不是 c

提前感谢。

5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
13

这是我最喜欢的功能之一,但对某些事情来说有点令人困惑。

因此,在为任何类创建模板时,名称基于类型的Name属性。例如,如果您在视图中执行<%= model.GetType().Name %>,您可以看到我的意思。例如,如果您的帐户列表是IList,则对类型调用.Name将返回List`1。那是一个合法的文件名,所以如果您将List`1.ascx放入DisplayTemplates文件夹中,它会找到并使用它。就我所知,它不会遍历类层次结构,因此,例如,如果您在那里放置了一个IEnumerable`1.ascx文件,它将无法找到它。

要循环显示,您需要将项目变量传递到lambda中,因此在您的示例中:

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

希望对你有所帮助。 保罗


谢谢你的回答,非常好用。我还有一个问题,如果我有两个不同子列表的独立对象,比如账户和人员,它们都有相同的对象名称List`1,那么你如何区分这两个对象?或者必须使用UIHint属性吗? - lancscoder
是的,两者将会相同。我认为 UIHint 会起作用(还没有尝试过),但你也可以将列表模板设置为通用(例如基于 IEnumerable,非泛型类型),然后在列表内部调用 DisplayFor,这样列表项每个都会有其正确的类型模板。另外,如果我没记错的话,你也可以在其中一个重载中以字符串形式传递显式模板名称。 - Paul
(编辑以修复Markdown语法中的反引号。) - G-Wiz
这个答案已经过时了,请查看其他答案或更新此答案以包含新的方法(更简单、更简洁)!谢谢。 - Piotr Kula

13

我知道这个问题有点旧,但至少在MVC 3中,当您想要使用列表时使用自定义显示/编辑模板,您可以传递模板的名称:

Html.DisplayFor(model => model.Account, "AccountList")

那么你的模板名称应该是 "AccountList"。


1
比被接受的答案好太多了。显然在回答时它是相关的,但 SO 的重点是更新旧答案或者赞同像你这样的新答案。谢谢。 - Piotr Kula

11

Brad Wilson的博客http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html有一个关于自定义对象的DisplayTemplates和EditorTemplates的示例,它讨论了一些问题,可能对您解决问题有所帮助。

关于您的第一个问题,重要的是您的模板必须位于系统查找匹配名称的文件夹中,例如:

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

(用EditorTemplates替换DisplayTemplates作为编辑器模板的搜索路径。)

下面的模板名称按顺序尝试:

  • ModelMetadata中的TemplateHint
  • ModelMetadata中的DataTypeName
  • 类型名称(见下面注释)
  • 如果对象不是复杂对象,则为“String”
  • 如果对象是复杂对象并且是接口,则为“Object”
  • 如果对象是复杂对象并且不是接口,则递归遍历类型的继承层次结构,尝试每个类型名称

对于您的第二个问题,我不确定答案。可以假设var c实际上等同于Account c吗? 当您编写Html.DisplayFor(x => x)时,您也可以编写Html.DisplayModelFor(c => c)吗?还是您希望像Html.DisplayFor(x => x.AccountName)这样?


嗨,谢谢你提供的链接,但它并不能完全回答我的问题。举个例子,我有一个客户,他有一个订单的子列表。目前,如果我想显示订单列表,我会创建一个 IEnumberable<order> 的 partial view 并循环每个对象创建一个表格。如果我想使用这个,我会说类似这样的话 Html.RenderPartial("OrdersTable",Model.Orders),但我想使用 Html.DisplayFor(x => x.Orders)。它会查找一个显示模板,但我不知道如何为列表调用显示模板。 - lancscoder
1
我已经为此苦思冥想了一段时间。我没有意识到搜索路径的重要性。将编辑您的帖子以澄清这一点。 - Dead account

1

在设置MVC 3应用程序时,应该允许下拉列表选择项目的外键不会呈现为下拉列表,而是呈现为静态输入。这可以通过为该字段创建自定义显示和视图来解决。 我们需要首先创建一个自定义部分视图,它将位于“〜/Views/Shared/DisplayTemplates/UserGuid.cshtml”和“〜/Views/Shared/EditTemplates/UserGuid.cshtml”中。其中一个的代码如下:

@model Guid

@{ 
    incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
    incMvcSite.Models.SecUser usr = db.SecUsers.Single(u => u.Guid == Model);
}
@usr.Display

这是一个显示模板,将查找引用表中的项目并显示它。 我们还需要以下模板的编辑:

@model Guid
@{ 
    incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
    SelectList items = new SelectList(db.SecUsers.OrderBy(i => i.Display).ToList(), "Guid", "Display", Model);
}
@Html.DropDownList("", items)

模板的编辑实现为一个下拉列表。原本,我们使用静态HTML代码,但在实现“前缀”时会出现问题。静态HTML代码无法处理HTML助手,因此建议您使用HTML.DropDownList()。 为了强制MVC框架使用新的显示和编辑模板,我们需要注释我们的模型项并添加以下行: [UIHint("UserGuid")]

这将导致MVC使用名为“UserGuid”的显示和编辑模板,它们只是部分视图。


-1

在之前的版本中不确定,但在MVC5中,您可以使用UIHint来指定模型中要使用哪个自定义显示/编辑模板,例如:

[UIHint("CustomAccountList")] public List Accounts{ get; set; }

或者在视图中像这样使用:

Html.DisplayFor(model => model.Accounts, "CustomAccountList")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,