2010-03-14 50 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

相關問題