2013-01-02 37 views
2

如您所知,ASP.NET MVC支持視圖中模型字段的自定義視圖覆蓋。在Views文件夾中有一個名爲Views\Shared\EditorTemplatesViews\Shared\DisplayTemplates等的文件夾,這些文件夾可以包含像Views\Shared\EditorTemplates\String.cshtml這樣的文件,它將覆蓋在帶有String字段的模型的視圖中調用@Html.EditorFor時使用的默認視圖。自定義類型依賴模板加載器

我想要做的是使用這種功能的自定義模板。我想要有一個像Views\Shared\GroupTemplates的文件夾,可能包含例如Views\Shared\GroupTemplates\String.cshtmlViews\Shared\GroupTemplates\Object.cshtml,我想創建一個HtmlHelper方法,它允許我這樣稱呼,例如Html.GroupFor(foo => foo.Bar),這將加載模板String.cshtml如果BarString屬性,在Object.cshtml否則模板。


預期行爲的完整示例;如果Views\Shared\GroupTemplates\String.cshtml包含此:

@model String 
This is the string template 

...和Views\Shared\GroupTemplates\Object.cshtml包含此:

@model Object 
This is the object template 

我有這樣一個模型:

class Foo 
{ 
    public bool Bar { get; set; } 
    public String Baz { get; set; } 
} 

而像在Views\Foo\Create.cshtml一個觀點:

@model Foo 
@Html.GroupFor(m => m.Bar) 
@Html.GroupFor(m => m.Baz) 

當我渲染視圖Create.cshtml,結果應該是這樣的:

This is the object template 
This is the string template 

應該如何GroupFor實施?

回答

1

的事情是,你可以很容易地指定您的視圖位置一樣,

html.Partial("~/Views/Shared/GroupTemplates/YourViewName.cshtml"); 

甚至通過實現自定義視圖引擎,對於例如覆蓋默認行爲,看到這個博客A Custom View Engine with Dynamic View Location

但你也想重用基於模型類型確定視圖名稱的邏輯。所以如果一個帶有String名字的視圖不存在,一個對象視圖會被拾取。這意味着要通過父類。

我當時一看EditorFor是如何實現的:

public static MvcHtmlString EditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
{ 
    return html.TemplateFor<TModel, TValue>(expression, null, null, DataBoundControlMode.Edit, null); 
} 

它採用TemplateFor方法,它的內部,你不能只是重複使用它。

所以我只能看到兩個選項:

  1. 通過檢查,如果有正確名稱的視圖文件存在試圖通過模型類型名稱和它的父類實現您的自定義邏輯。如果您發現正確的視圖,只需在助手中使用部分擴展。
  2. 嘗試使用反射來調用內部方法。但是這種方法更像是一種破解而非解決方案。

希望它有幫助!

+0

我看了[ASP.NET MVC的源代碼](http://aspnetwebstack.codeplex.com),並簡單地從那裏複製了類型鏈生成算法。這基本上就是你說的,所以我會接受你的答案。 – dflemstr