C# 与ASP.NET MVC自动脚手架模板抗争

C# 与ASP.NET MVC自动脚手架模板抗争,c#,html,asp.net-mvc,templates,C#,Html,Asp.net Mvc,Templates,我正在尝试为索引视图编写一个自动脚手架模板。我希望能够传入一组模型或视图模型(例如,IQueryable),并返回一个HTML表,该表使用DisplayName属性作为标题(th元素),使用HTML.Display(propertyName)属性作为单元格(td元素)。每行应对应于集合中的一项 以下是我目前掌握的情况: pm.ShowForDisplay&!ViewData.TemplateInfo.Visited(pm)); %> 这有两个问题: 我希望它是通用的。因此,我想替换var

我正在尝试为索引视图编写一个自动脚手架模板。我希望能够传入一组模型或视图模型(例如,
IQueryable
),并返回一个HTML表,该表使用
DisplayName
属性作为标题(
th
元素),使用
HTML.Display(propertyName)
属性作为单元格(
td
元素)。每行应对应于集合中的一项

以下是我目前掌握的情况:



pm.ShowForDisplay&!ViewData.TemplateInfo.Visited(pm));
%>

这有两个问题:

  • 我希望它是通用的。因此,我想替换
    var items=(IQueryable)模型带有
    var项=(IQueryable)模型或类似的东西

  • 创建视图时,会自动为我创建属性
    Html
    ,但此
    HtmlHelper
    适用于整个集合。我需要以某种方式创建一个
    itemHtml
    对象,该对象只应用于
    foreach
    循环中的当前项。但是,我不知道如何做到这一点,因为
    HtmlHelper
    的构造函数不接受
    Model
    对象

  • 我该如何解决这两个问题?

    您研究过这个问题了吗?当然,有人编写了一个扩展方法来默认显示所有属性。如果不是的话,这应该不难

    edit2-我想我不相信我周日的答案。我之前误读了这个问题,没有意识到Html.Display()是MVC2模板化的输入。(我在我的店里做了一些完全不同的输入生成器,所以我没有注意到它的名字。我只是认为Display显示了它的价值。)总之,我在这里看到了两个选项

    1) 拉出MVC2源代码或中断反射程序,编写您自己的方法,而不是扩展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。我建议您选择另一条路线。

    对于Generic IQueryable部分,您为什么不直接将其转换为IQueryable

    var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;
    
    我不确定这是否有效…

    遗憾的是,您无法做到:

    <%@ 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所展示的那样,它为您提供了开箱即用的脚手架。(我相信你一定知道,为了完整起见)

    如果您查看源代码,尤其是
    DefaultDisplayTemplates.cs
    ,它基本上都包含在一个HTMLHelper中,作为一个视图。也许不必为视图使用自动生成的类(正如我非常喜欢asp.net mvc一样,默认视图渲染引擎是一个非常麻烦的问题),而应该使用一个按照asp.net mvc RTM实现脚手架的方式建模的HTMLHelper扩展。我想这也为代码重用打开了可能性(尽管几乎所有东西都是内部的)

    如果ASP.NET MVC脚手架允许传入一个自定义模板来更改html(如果您不喜欢默认的
    等等),那就太好了。对我来说,这是ASP.net MVC(硬编码的错误处理/脚手架HTML)的弱点之一


    如果您不喜欢字符串构建HTML,那么当您的scaffoldHtmlHelper扩展收集了足够的信息以充分键入粒度视图时,您的扩展可以调用更细粒度的局部视图(如
    ScaffoldCaption.ascx

    菲尔·哈克来营救


    我将查看MvcContrib网格。谢谢你的提示。至于你的第二个答案,你能告诉我如何编写扩展方法吗?我的意思是,通常我知道如何编写扩展方法,但我不清楚如何使用当前的
    项作为模型创建自己的
    HtmlHelper
    实例。您可以使用property.GetValue(item,null)来获取值。我只是喜欢用一种重用的方法来包装这种东西。我想它不需要是一个扩展方法。我一秒钟也没想。但是
    property.GetValue(…)
    并不等同于
    Html.Display(…)
    。我需要类似于
    var itemHtml=??
    ,然后调用
    itemHtml.Display(property.DisplayName)
    。什么应该是
    ?我对我的问题做了一些编辑。希望现在我想问的问题更清楚一点。谢谢你的回答,但我对你建议的三件事都没有把握。如果我将其转换为
    IQueryable
    而不是
    IQueryable
    ,我将失去使用LINQ的能力,因此
    items.First()
    不会编译。如果我尝试仅在项目上使用默认的
    Display()
    DisplayFor()
    帮助程序,即使删除了所有自定义模板,也会得到一个空白显示。至于您建议尝试
    property.GetValue()
    GetValue()
    甚至不是
    ModelMetadata
    上的方法(参考:)。还有其他想法吗?嗨,Martijn,我不介意构建自己的HtmlHelper方法,但是无论我使用.aspx文件还是.cs文件,我仍然会遇到如何为集合/列表中的各个项目实例化帮助程序的问题。当您创建一个新视图时,该
    Html
    属性将为
    Html.DisplayFor(o => property.GetValue(item))
    
    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<T>>" %>
    
    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<T>" %>