我正在尝试为Index视图编写一个自动脚手架模板。我希望能够传递一组模型或视图模型(例如IQueryable<MyViewModel>
)并获取一个HTML表格,该表格使用DisplayName
属性作为标题({{1}元素)和th
用于单元格(Html.Display(propertyName)
元素)。每行应对应于集合中的一个项目。
这是我到目前为止所拥有的:
td
有两个问题:
我希望它是通用的。因此,我想将<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;
// How do I make this generic?
var properties = items.First().GetMetadata().Properties
.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm));
%>
<table>
<tr>
<%
foreach(var property in properties)
{
%>
<th>
<%= property.DisplayName %>
</th>
<%
}
%>
</tr>
<%
foreach(var item in items)
{
HtmlHelper itemHtml = ????;
// What should I put in place of "????"?
%>
<tr>
<%
foreach(var property in properties)
{
%>
<td>
<%= itemHtml.Display(property.DisplayName) %>
</td>
<%
}
%>
</tr>
<%
}
%>
</table>
替换为var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;
或其他类似内容。
创建视图时会自动为我创建属性var items = (IQueryable<T>)Model;
,但此Html
适用于整个集合。我需要以某种方式创建一个HtmlHelper
对象,该对象仅适用于itemHtml
循环中的当前项。但是,我不知道如何执行此操作,因为foreach
的构造函数不会使用HtmlHelper
对象。
如何解决这两个问题?
答案 0 :(得分:3)
答案 1 :(得分:0)
对于geniric IQueryable部分,为什么不简单地将它转换为IQueryable ......
var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;
和你的模板是什么,它与添加视图时的默认列表模板几乎不一样...如果你想自定义它,我想你最好找一下List.tt模板。您可以修改它以使用Html.Display而不是Html.Encode。
或者您可以尝试使用
Html.DisplayFor(o => property.GetValue(item))
我不确定这是否有用......
答案 2 :(得分:0)
可悲的是你不能这样做:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<T>>" %>
甚至
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<T>" %>
ASP.NET MVC实现了一个Html.DisplayForModel(),因为Brad Wilson显示on his blog,它为您提供了开箱即用的脚手架。 (我相信你知道的,提到完整性)。
如果您查看MVC 2 RTM Source Code源代码,特别是DefaultDisplayTemplates.cs
,它们基本上都包含在HTMLHelper中,就像视图一样。也许不是与视图的自动生成类进行斗争(尽管我喜欢asp.net mvc,默认视图渲染引擎是一个彻头彻尾的痛苦),而是按照ASP.NET MVC RTM实现脚手架的方式建模的HTMLHelper扩展。我想这会为代码重用提供更多的可能性(尽管几乎所有内容都是内部的)。
如果您不是默认<div class=\"display-field\">
等的粉丝,那么如果ASP.NET MVC脚手架允许传入自定义模板以更改html,那将是很好的。对我来说,这是ASP.net MVC的弱点之一('硬编码'错误处理/脚手架HTML)。
如果您不是构建HTML的字符串粉丝,那么当您的脚手架HTMLHelper扩展程序收集了足够的信息以充分键入粒度视图时,您的扩展程序可以调出更细粒度的部分视图(例如ScaffoldCaption.ascx
)。
答案 3 :(得分:-1)
你有没有看过MVCContrib Grid?当然有人编写了一个扩展方法来默认显示所有属性。如果不是,那应该不难。
edit2-我想在周日不相信我的答案。我之前误解了这个问题并且没有意识到Html.Display()是MVC2模板化输入。 (我在我的店里做了一些根本不同的输入构建器,所以我没有拿起名字。我只是觉得Display显示了价值。)无论如何,我在这里看到两个选项。
1)拉出MVC2源或分解Reflector并编写自己的方法,而不是扩展HtmlHelper。
2)你可以在这里使用反射来构建一个新的HtmlHelper实例,但它并不漂亮。 (我没有测试过,但应该可以使用。)
var modelType = Html.GetType().GetGenericParameters()[0]; var itemHtmlType = typeof(HtmlHelper<>).MakeGenericType(modelType); var itemHtmlCtor = itemHtmlType.GetConstructor(typeof(ViewContext), typeof(IViewDatacontainer), typeof(RouteCollection)); var itemHtml = itemHtmlCtor.Invoke(Html.ViewContext, Html.ViewDataContainer, Html.RouteCollection);
你会得到一个对象,所以你必须使用反射来调用itemHtml.Dipslay。我建议走另一条路。