2010-03-14 119 views
2

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

这是我到目前为止有:


<%@ 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<T>)Model;代替var items = (IQueryable<TestProj.ViewModels.TestViewModel>)Model;,或者是这个效果。

  2. 属性Html是在创建视图时为我自动创建的,但是这个HtmlHelper适用于整个集合。我需要以某种方式创建一个itemHtml对象,该对象仅适用于foreach循环中的当前项目。然而,我不确定如何做到这一点,因为HtmlHelper的构造函数不带Model对象。

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

回答

-1

你看过MVCContrib Grid吗?当然有人写了一个扩展方法来默认显示所有属性。如果不是,它不应该是困难的。

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。我建议走一条不同的路线。

+0

我会看看MvcContrib网格。谢谢你的提示。至于你的第二个答案,你能给我一些关于如何编写扩展方法的想法吗?我的意思是,我知道如何编写扩展方法,但我不清楚如何使用当前的'item'作为模型创建自己的'HtmlHelper'实例。 – devuxer 2010-03-15 00:52:23

+0

您可以使用property.GetValue(item,null)来获取值。我只是喜欢用一种方法重新包装这种东西。我想它不需要是一个扩展方法。我没有想一秒钟。 – Ryan 2010-03-15 01:22:17

+0

但是'property.GetValue(...)'不等于'Html.Display(...)'。我需要'var itemHtml = ????'之类的东西,然后我会调用'itemHtml.Display(property.DisplayName)'。应该怎么做? – devuxer 2010-03-15 04:50:11

0

为geniric IQueryable的一部分,你为什么不干脆将其转换为一个IQueryable ...

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

,什么是你的模板,是不是几乎相同的默认列表模板当你添加一个视图...如果你想定制它,我认为你最好看看List.tt模板。你可以修改它来使用Html.Display而不是Html.Encode。

或者你可以尝试使用

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

我不知道这是否会工作...

+0

感谢您的回答,但我没有运气与您建议的三件事情中的任何一件。如果我使用'IQueryable'而不是'IQueryable',我失去了使用LINQ的能力,所以'items.First()'不能编译。如果我尝试在项目上使用默认的Display()或DisplayFor()帮助程序,即使删除了所有自定义模板,也会显示空白。至于你的建议尝试'property.GetValue()','GetValue()'甚至不是'ModelMetadata'上的方法(参考:http://msdn.microsoft.com/en-us/library/system.web .mvc.modelmetadata_members%28VS.100%29.aspx)。任何其他想法? – devuxer 2010-03-22 17:20:09

0

可悲的是,你不能做的:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<T>>" %> 

甚至

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<T>" %> 

ASP.NET MVC实现了一个Htm l.DisplayForModel()如布莱德威尔逊显示on his blog它为您开箱即用脚手架。 (我相信你知道,完整性提及)。

如果你看看MVC 2 RTM Source Code源代码,特别是DefaultDisplayTemplates.cs,它基本上都包含在HTMLHelper中,就像一个View一样。也许不是与视图中的自动生成的类(尽管我喜欢asp.net mvc,默认视图渲染引擎完全是痛苦)一样,使用HTMLHelper扩展模仿ASP.NET MVC RTM如何实现脚手架。我想这会打开更多的代码重用的可能性(尽管几乎所有东西都是内部的)。

如果ASP.NET MVC脚手架允许自定义模板传入以更改HTML,如果您不是默认的默认粉丝,那将会很不错。对我来说,这是ASP.net MVC('硬编码'错误处理/脚手架HTML)的弱点之一。

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

+0

嗨Martijn,我不介意建立我自己的HtmlHelper方法,但无论我使用.aspx文件还是.cs文件,我仍然遇到如何为集合/列表中的单个项目实例化助手的问题。当你创建一个新的视图时,这个'Html'属性会被填充。现在我需要为列表/集合中的每个项目创建等效对象。我该怎么做呢?这就是'????'的意思。 – devuxer 2010-03-23 22:37:42

+0

另外,我无法在源代码(http://aspnet.codeplex.com/SourceControl/changeset/view/23011#)中找到DefaultDisplayTemplates.cs。 – devuxer 2010-03-23 23:00:33

相关问题