【问题标题】:Struggling with ASP.NET MVC auto-scaffolder template苦苦挣扎于 ASP.NET MVC 自动脚手架模板
【发布时间】:2010-03-14 20:45:53
【问题描述】:

我正在尝试为索引视图编写一个自动脚手架模板。我希望能够传入模型或视图模型的集合(例如,IQueryable<MyViewModel>)并返回一个 HTML 表格,该表格使用DisplayName 属性作为标题(th 元素)和@987654324 @ 用于单元格(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>

这有两个问题:

  1. 我希望它是通用的。所以,我想用var items = (IQueryable&lt;T&gt;)Model; 或类似的东西替换var items = (IQueryable&lt;TestProj.ViewModels.TestViewModel&gt;)Model;

  2. 创建视图时会自动为我创建属性Html,但此HtmlHelper 适用于整个集合。我需要以某种方式创建一个itemHtml 对象,该对象仅适用于foreach 循环中的当前项目。但是,我不确定如何执行此操作,因为 HtmlHelper 的构造函数不采用 Model 对象。

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

【问题讨论】:

    标签: c# html asp.net-mvc templates


    【解决方案1】:
    【解决方案2】:

    对于通用的 IQueryable 部分,您为什么不简单地将其转换为 IQueryable...

    var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;
    

    你的模板是做什么用的,是不是和你添加视图时的默认列表模板几乎一样...如果你想自定义它,我认为你最好寻找 List.tt 模板.您可以修改它以使用 Html.Display 而不是 Html.Encode。

    或者你可以尝试使用

    Html.DisplayFor(o => property.GetValue(item))
    

    我不确定这是否可行...

    【讨论】:

    • 感谢您的回答,但我对您建议的三件事都不满意。如果我转换为IQueryable 而不是IQueryable&lt;T&gt;,我将失去使用LINQ 的能力,因此items.First() 无法编译。如果我尝试在项目上仅使用默认的 Display()DisplayFor() 帮助程序,即使我删除了所有自定义模板,我也会得到一个空白显示。至于你建议尝试property.GetValue()GetValue() 甚至不是ModelMetadata 上的方法(参考:msdn.microsoft.com/en-us/library/…)。还有其他想法吗?
    【解决方案3】:

    很遗憾你做不到:

    <%@ 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 中,就像View 一样。也许与其与视图的自动生成类作斗争(尽管我很喜欢 asp.net mvc,但默认的视图渲染引擎是一件非常痛苦的事情),而是使用一个 HTMLHelper 扩展,该扩展模仿了 ASP.NET MVC RTM 如何实现脚手架。我想这也会为代码重用提供更多可能性(尽管几乎所有内容都是内部的)。

    如果您不喜欢默认的&lt;div class=\"display-field\"&gt; 等,如果 ASP.NET MVC 脚手架允许传入自定义模板来更改 html,那就太好了。对我来说,这是 ASP.net MVC 的弱点之一(“硬编码”错误处理/脚手架 HTML)。

    如果您不喜欢构建 HTML 的字符串,那么当您的脚手架 HTMLHelper 扩展程序收集到足够的信息以充分键入粒度视图时,您的扩展程序可能会调用更粒度的局部视图(如 ScaffoldCaption.ascx)。

    【讨论】:

    • 嗨 Martijn,我不介意构建自己的 HtmlHelper 方法,但是无论我使用 .aspx 文件还是 .cs 文件,我仍然会遇到如何为个人实例化帮助器的问题集合/列表中的项目。当您创建一个新视图时,该 Html 属性会为您填充。现在我需要为列表/集合中的每个项目创建等效对象。我该怎么做呢?这就是???? 的意义所在。
    • 另外,我在源代码 (aspnet.codeplex.com/SourceControl/changeset/view/23011#) 中找不到 DefaultDisplayTemplates.cs。
    【解决方案4】:

    您查看过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。我建议走不同的路线。

    【讨论】:

    • 我将研究 MvcContrib 网格。谢谢你的提示。至于你的第二个答案,你能给我一些关于如何编写扩展方法的想法吗?我的意思是,我一般都知道如何编写扩展方法,但我不清楚如何以当前的 item 为模型创建自己的 HtmlHelper 实例。
    • 您可以使用 property.GetValue(item, null) 来获取值。我只是更喜欢将这种东西包装在一种可重用的方法中。我想它不需要是扩展方法。我没想到。
    • 但是property.GetValue(...) 不等于Html.Display(...)。我需要var itemHtml = ???? 之类的东西,然后我会打电话给itemHtml.Display(property.DisplayName)???? 应该是什么?
    • 我稍微编辑了我的问题。希望现在我要问的问题更清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    • 2018-07-20
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    相关资源
    最近更新 更多