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是問題