ASP.Net MVC:Html.Display()用于Collection中的对象

时间:2010-10-19 20:53:36

标签: asp.net-mvc html-helper asp.net-mvc-partialview

使用适当的视图模板绘制项目的标准MVC示例是:

Html.DisplayFor(m => m.Date)

如果Model对象具有名为Date of DateTime的属性,则返回带有Display / DateTime.ascx模板中的HTML的字符串。

假设您想要执行相同的操作,但无法使用强类型版本 - 您在编译时不知道此View的Model类型。你使用旧的:

Html.Display( “日期”);

所以这是困难的部分。

假设模型是IEnumerable。您不知道这些对象在编译时是什么,但在运行时它们恰好是Date类型为Date的对象,如:

public class ModelClass
{
    public DateTime Date { get; set; }
}

现在假设您希望View迭代这些对象并渲染每个对象。如果你所关心的只是你可以做到的价值:

<%
StringBuilder sb = new StringBuilder();
foreach(object obj in (IEnumerable<object>)Model)
{
    Type type = obj.GetType();

    foreach(PropertyInfo prop in type.GetProperties())
    {
        // TODO: Draw the appropriate Display PartialView/Template instead
        sb.AppendLine(prop.GetValue(obj, null).ToString());
    }
}
%>
<%= sb.ToString() %>

我显然采取了一些捷径来保持这个例子的重点。

这就是重点 - 我如何实现我为自己写的TODO?我不只是想获得价值 - 我希望它的格式很好,如Html.Display(“Date”)。但是,如果我只是调用Html.Display(“Date”),它会检查Model,这是一个IEnumerable,用于名为Date的属性,它当然没有。 Html.Display不会将对象作为参数用作模型(如Html.Display(obj,“Date”),并且我可以找到的所有类和方法都在内部,所以我可以' t调整并直接调用它们。

必须有一些简单的方法来完成我想要做的事情,但我似乎无法找到它。

只是为了确保我清楚 - 这是DateTime.ascx代码的一个例子:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime>" %>
<%= Model.ToString("MM/dd/yyyy") %>

理想情况下,此视图的输出可以采用任何模型,但在本例中是上面3个这些ModelClass对象的列表,将是:

2001年11月10日 2002年11月10日 11/10/2003

因为代码会找到DateTime的Display PartialView并为每个代码适当地渲染它。

那么 - 我如何实现TODO?

2 个答案:

答案 0 :(得分:8)

在Phil Haack的这篇优秀文章中查看模板代码。它似乎接近你要找的东西:http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx

答案 1 :(得分:0)

我找到了一个可能的解决方案,但我并不喜欢它;它需要使用几个基于文件的模板,这意味着您无法将其轻松地抽象到代码库中以便在多个项目中使用。

观点:

<%
StringBuilder sb = new StringBuilder();

Type itemType = Model.GetType().GetGenericArguments()[0];

sb.AppendLine("<table>");

// Pass in the Model (IEnumerable<object>)'s generic item type as
// the Model for a PartialView that draws the header
sb.Append(Html.Partial("DisplayTableHead", itemType));

foreach(object item in (IEnumerable<object>)Model)
{
    sb.Append(Html.Partial("DisplayTableRow", item));
}

sb.AppendLine("</table>");
%>
<%= sb.ToString() %>

查看/共享/ DisplayTableHead.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Type>" %>
<tr>
<%
foreach (PropertyInfo prop in Model.GetProperties())
{
%>
<th><%= prop.Name %></th>
<%
}
%>
</tr>

查看/共享/ DisplayTableRow.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<tr>
<%
Type modelType = Model.GetType();

foreach (PropertyInfo modelField in modelType.GetProperties())
{
%>
<td><%= Html.Display(modelField.Name) %></td>
<%
}
%>
</tr>

但我现在看到了这个解决方案的主要缺陷,即 Clicktricity 发布的解决方案确认了ModelMetadata中的详细信息 - 比如该特定属性是否设置为显示,是否复杂等等。