ASP.NET MVC 3 – 部分VS显示模板与编辑器模板

所以,标题应该说明一切。

为了在ASP.NET MVC中创build可重用的组件,我们有3个选项(可能是其他我没有提到的):

部分视图:

@Html.Partial(Model.Foo, "SomePartial") 

定制编辑器模板:

 @Html.EditorFor(model => model.Foo) 

自定义显示模板:

 @Html.DisplayFor(model => model.Foo) 

根据实际的View / HTML,这三个实现是相同的:

 @model WebApplications.Models.FooObject <!-- Bunch of HTML --> 

所以,我的问题是 – 什么时候/如何决定使用哪一个?

我真正想要的是在创build一个问题之前问自己的问题列表,可以使用这些答案来决定使用哪个模板。

以下是我用EditorFor / DisplayForfind的两件事情:

  1. 它们在呈现HTML帮助器时尊重模型层次结构(例如,如果在“Foo”模型中有“Bar”对象,则“Bar”的HTML元素将以“Foo.Bar.ElementName”呈现,而部分将具有“的ElementName“)。

  2. 更健壮的,例如,如果您的ViewModel中有一个List<T> ,您可以使用@Html.DisplayFor(model => model.CollectionOfFoo) ,而且MVC足够聪明,可以看到它是一个集合并呈现出单个显示为每个项目(而不是一个部分,这将需要一个明确的循环)。

我也听说DisplayFor呈现“只读”模板,但我不明白 – 我不能在那里扔表吗?

有人能告诉我其他一些原因吗? 比较三个地方是否有列表/文章?

EditorFor vs DisplayFor很简单。 这些方法的语义是分别生成编辑/插入和显示/只读视图。 显示数据时使用DisplayFor (即生成包含模型值的div和span)。 编辑/插入数据时使用EditorFor (即在表单中生成input标签时)。

以上方法是以模型为中心的。 这意味着他们会考虑模型元数据(例如,您可以使用[UIHintAttribute][DisplayAttribute]注释您的模型类,这将影响select哪个模板来生成模型的UI,它们通常也用于数据模型(即表示数据库中的行的模型等)

另一方面, Partial是以视图为中心的,因为你主要关心的是select正确的局部视图。 该视图不一定需要模型才能正常工作。 它可以有一个共同的标记,在整个网站被重用。 当然,通常情况下,您希望影响此部分的行为,在这种情况下,您可能希望传入适当的视图模型。

你没有问到@Html.Action ,这里也值得一提。 您可以将其视为Partial的更强大版本,因为它执行控制器子操作,然后呈现视图(通常是部分视图)。 这很重要,因为子操作可以执行不属于局部视图的其他业务逻辑。 例如,它可以代表购物车组件。 使用它的原因是避免在应用程序中的每个控制器中执行与购物车相关的工作。

最终select取决于你在应用程序中build模的是什么。 另外请记住,你可以混合搭配。 例如,你可以有一个调用EditorFor助手的局部视图。 这真的取决于你的应用程序是什么,以及如何分解它,以鼓励最大限度的代码重用,同时避免重复。

您当然可以自定义DisplayFor以显示可编辑的表单。 但是,对于DisplayFor ,这个约定是readonlyEditorFor是为了编辑。 按照惯例将确保无论你传入DisplayFor ,它将做同样的事情。

只是为了让我的2c值得,我们的项目是使用几个jQuery选项卡的部分视图,每个选项卡使用自己的部分视图呈现其字段。 这工作得很好,直到我们添加了一个function,其中一些选项卡共享一些常见的字段。 我们的第一个方法是用这些常见的字段创build另一个局部视图,但是当使用EditorFor和DropDownListFor来渲染字段和下拉菜单时,这变得非常笨重。 为了获得独特的ID和名称,我们不得不使用一个前缀来显示字段,这取决于呈现它的父部分视图:

  <div id="div-@(idPrefix)2" class="toHide-@(idPrefix)" style="display:none"> <fieldset> <label for="@(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label> <input name="@(idPrefix).Frequency" id="@(idPrefix)_Frequency" style="width: 50%;" type="text" value="@(defaultTimePoint.Frequency)" data-bind="value: viewState.@(viewStatePrefix).RecurringTimepoints.Frequency" data-val="true" data-val-required="The Frequency field is required." data-val-number="The field Frequency must be a number." data-val-range-min="1" data-val-range-max="24" data-val-range="The field Frequency must be between 1 and 24." data-val-ignore="true"/> @Html.ValidationMessage(idPrefix + ".Frequency") ... etc </fieldset> </div> 

这非常丑陋,所以我们决定使用编辑器模板,而这样做更清晰。 我们添加了一个新的视图模型与公共领域,添加了一个匹配的编辑器模板,并使用编辑器模板从不同的父视图呈现字段。 编辑器模板正确地呈现ID和名称。

所以简而言之,我们使用编辑器模板的一个令人信服的理由是需要在多个选项卡中呈现一些通用字段。 部分视图不是为此devise的,但“编辑器模板”完美地处理场景。

到目前为止还没有提到的另一个区别是,partialview不会在模板中添加模型前缀。 这是问题

使用_partial视图的方法,如果:

  1. 查看中心逻辑
  2. 只有在这个视图中保留所有的_partial视图相关的HTML。 在模板方法中,您将不得不在Template View之外保留一些HTML,如“主标题”或任何外部边框/设置。
  3. 要使用URL.Action("action","controller")以逻辑(从控制器)呈现部分视图。

使用模板的原因:

  1. 要删除ForEach(Iterator) 。 模板足以将Model识别为列表types。 它会自动执行。
  2. 模型中心逻辑。 如果在同一个显示模板文件夹中find多个视图,则渲染将取决于传递模型。