2

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

我想做的是将此功能用于自定义类型的模板。我想要一个这样的文件夹Views\Shared\GroupTemplates,其中可能包含例如Views\Shared\GroupTemplates\String.cshtmland Views\Shared\GroupTemplates\Object.cshtml,并且我想创建一个HtmlHelper允许我调用 example 的方法,如果是属性,Html.GroupFor(foo => foo.Bar)它将加载模板,否则加载模板。String.cshtmlBarStringObject.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实施?

4

1 回答 1

1

问题是您可以像这样轻松地指定您的视图位置

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

甚至通过实现自定义视图引擎来覆盖默认行为,例如,请参阅此博客A Custom View Engine with Dynamic View Location

但是您还想重用根据模型类型确定视图名称的逻辑。因此,如果不存在具有字符串名称的视图,则会拾取对象视图。这意味着要通过父类。

我看过 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. 通过尝试模型类型名称及其父类来检查是否存在具有正确名称的视图文件,从而实现您的自定义逻辑。如果您找到合适的视图,只需在帮助程序中使用 Partial 扩展。
  2. 尝试使用反射来调用内部方法。但这种方法更像是一种 hack,而不是一种解决方案。

希望能帮助到你!

于 2013-01-02T14:58:41.850 回答