自定义类型相关的模板加载器

时间:2013-01-02 10:30:46

标签: c# asp.net-mvc

您可能知道,ASP.NET MVC支持视图中模型字段的自定义视图覆盖。 Views文件夹中有一些名为Views\Shared\EditorTemplatesViews\Shared\DisplayTemplates等特殊文件夹,这些文件夹可以包含Views\Shared\EditorTemplates\String.cshtml等文件,这些文件将覆盖调用时使用的默认视图@Html.EditorFor在包含String字段的模型的视图中。

我想要做的是将此功能用于自定义类型的模板。我希望有一个像Views\Shared\GroupTemplates这样的文件夹,可能包含例如Views\Shared\GroupTemplates\String.cshtmlViews\Shared\GroupTemplates\Object.cshtml,我想创建一个HtmlHelper方法,允许我调用Html.GroupFor(foo => foo.Bar),例如String.cshtml Bar {1}}是一个String属性,另一个是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 个答案:

答案 0 :(得分: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. 尝试使用反射来调用内部方法。但这种方法更像是黑客而不是解决方案。
  3. 希望它有所帮助!