291

因此,标题应该说明问题。ASP.NET MVC 3 - 部分vs显示模板与编辑器模板

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

管窥:

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

自定义编辑器模板:

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

自定义显示模板:

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

在实际查看/ HTML方面,所有三种实现是相同的:

@model WebApplications.Models.FooObject 

<!-- Bunch of HTML --> 

所以,我的问题是 - 当/你如何决定三个使用哪一个?

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

这里的两件事情我已经找到更好EditorFor/DisplayFor:

  1. 他们尊重模型层次渲染HTML佣工(例如,当你有你的“富”模型中的“酒吧”的对象时, “Bar”的HTML元素将以“Foo.Bar.ElementName”呈现,而部分将具有“ElementName”)。

  2. 更强大,例如,如果你有在你的视图模型东西List<T>,你可以使用@Html.DisplayFor(model => model.CollectionOfFoo)和MVC是足够聪明,看到这是一个收集和呈现出每个项目单显示(而不是一个局部,这将需要一个明确的for循环)。

我也听过DisplayFor呈现“只读”模板,但我不明白 - 我不能在那里扔一个表单吗?

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

+0

后面的编辑和显示模板的概念的明确定义的partialview不加前缀模式文档为asp.net mvc 2.模板是遵循特定约定的偏见。使模板比旧部分更好或更差的情况几乎严格取决于该约定是否值得遵守您的应用程序。 – 2011-02-18 04:41:00

+4

+1好问题。 – 2013-08-24 19:53:06

回答

285

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

上述方法是模型为中心。这意味着,他们将采取模型元数据考虑在内(例如,你可以用[UIHintAttribute][DisplayAttribute]注解你的模型类,这将影响该模板被选择产生的模型的用户界面。他们通常也用于数据模型(即代表数据库中的行的模型等)

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

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

最终选择取决于您在应用程序中建模的是什么。另外请记住,你可以混合搭配。例如,您可以使用调用EditorFor帮助器的局部视图。这实际上取决于你的应用程序是什么以及如何分解它以鼓励最大程度地重用代码,同时避免重复。

+4

这是一个很好的答案,正是我所期待的。事实上,我在为你回答这个问题而努力。 :)感谢marcin。 – RPM1984 2011-02-18 04:45:11

+0

如何使用注释为单个属性指定显示模板和编辑器模板? – stormwild 2011-10-24 10:00:45

14

您当然可以可以定制DisplayFor来显示可编辑的表格。但约定为DisplayForreadonlyEditorFor以供编辑。坚持大会将确保不管你通过什么DisplayFor,它会做同样的事情。

13

只是为了让我的2c值得,我们的项目使用了多个jQuery选项卡的局部视图,并且每个选项卡使用其自己的局部视图呈现其字段。这工作得很好,直到我们添加了一个功能,其中一些选项卡共享一些常用字段。我们的第一个方法是使用这些常用字段创建另一个局部视图,但使用EditorFor和DropDownListFor呈现字段和下拉列表时,这会变得非常笨重。为了让IDS和独特的名字,我们不得不渲染取决于父局部视图中的前缀是使其领域:

<div id="[email protected](idPrefix)2" class="[email protected](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: [email protected](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和名称。

因此,简而言之,我们使用编辑器模板的一个充分理由是需要在多个选项卡中呈现一些常用字段。部分视图不是为此设计的,但编辑器模板完美地处理场景。

1

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

  1. 观为中心的逻辑
  2. 什么让所有_partial视图相关的HTML仅这一观点。在模板方法中,您必须在模板视图之外保留一些HTML,如“主标题或任何外部边框/设置。
  3. 想要使用URL.Action("action","controller")以逻辑(从控制器)呈现部分视图。

理由使用模板:

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

尚未到目前为止提到的另一个区别是,一个模板做 Here是问题