ASP.NET MVC 3-部分テンプレートvs表示テンプレートvsエディターテンプレート


303

そのため、タイトルはそれ自体が物語っています。

ASP.NET MVCで再利用可能なコンポーネントを作成するには、3つのオプションがあります(私が言及しなかった他のオプションも考えられます)。

部分図:

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

カスタムエディターテンプレート:

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

カスタム表示テンプレート:

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

実際のビュー/ HTMLに関しては、3つの実装はすべて同じです。

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

それで、私の質問は-いつ/どのようにして3つの中のどれを使うかを決めるのですか?

私が本当に探しているのは、作成する前に自問する質問のリストです。その回答を使用して、使用するテンプレートを決定できます。

ここに、EditorFor / DisplayForで私が見つけた2つの点があります。

  1. HTMLヘルパーをレンダリングするときにモデル階層を尊重します(たとえば、「Foo」モデルに「Bar」オブジェクトがある場合、「Bar」のHTML要素は「Foo.Bar.ElementName」でレンダリングされますが、パーシャルは「 ElementName」)。

  2. たとえばList<T>、ViewModelに何かがある場合は、を使用できます。MVCは、それが@Html.DisplayFor(model => model.CollectionOfFoo)コレクションであることを確認し、各項目の単一の表示をレンダリングするのに十分スマートです(Partialは、明示的なループ)。

DisplayForが「読み取り専用」テンプレートをレンダリングすることも聞いたことがありますが、理解できません-フォームをそこにスローできませんでしたか?

誰か他の理由を教えてもらえますか?3つを比較するリスト/記事はどこかにありますか?


エディターおよび表示テンプレートの背後にある概念は、asp.net mvc 2のドキュメントで明確に定義されています。テンプレートは、特定の規則に準拠する部分テンプレートです。テンプレートを古いパーシャルよりも良くも悪くもする状況は、その規則がアプリケーションで遵守する価値があるかどうかにほぼ厳密に依存しています。
Nick Larsen、

回答:


301

EditorForvs DisplayForは単純です。メソッドのセマンティクスは、編集/挿入および表示/読み取り専用ビューを(それぞれ)生成することです。使用DisplayFor(あなたがモデル値を含んでdivタグとスパンを生成する際にIE)のデータを表示するとき。EditorForデータを編集/挿入するとき(つまり、フォーム内に入力タグを生成するとき)に使用します。

上記の方法はモデル中心です。つまり、モデルメタデータが考慮されます(たとえば、モデルクラスに[UIHintAttribute]またはで注釈を付けることができます。[DisplayAttribute]これにより、モデルのUIを生成するために選択されるテンプレートに影響します。通常、これらはデータモデル(つまり、データベースの行などを表す)

一方Partial、正しい部分ビューを選択することに主に関心があるという点で、ビュー中心です。ビューは、正しく機能するためにモデルを必ずしも必要としません。サイト全体で再利用されるマークアップの共通セットを持つことができます。もちろん、多くの場合、このパーシャルの動作に影響を与えたい場合は、適切なビューモデルを渡す必要があります。

@Html.Actionここでも言及に値するものについては質問しませんでした。Partialこれは、コントローラーの子アクションを実行してビュー(通常は部分ビュー)をレンダリングするという点で、のより強力なバージョンと考えることができます。子アクションは部分ビューに属さない追加のビジネスロジックを実行できるため、これは重要です。たとえば、ショッピングカートコンポーネントを表すことができます。これを使用する理由は、アプリケーションのすべてのコントローラーでショッピングカート関連の作業を実行しないようにするためです。

最終的には、アプリケーションで何をモデル化するかによって選択が異なります。また、組み合わせることができることを忘れないでください。たとえば、EditorForヘルパーを呼び出す部分的なビューを持つことができます。それは、アプリケーションが何であるか、そして繰り返しを避けながら最大限のコード再利用を促進するためにそれをどのように因数分解するかに本当に依存します。


4
それは素晴らしい答えです。まさに私が探していたものです。実際には、私があなたが来てこれに答えるという事実に頼っていました。:)ありがとうmarcin。
RPM1984

注釈を使用して、単一のプロパティの表示テンプレートとエディターテンプレートをどのように指定しますか?
stormwild

3
@stormwildは、規則を使用して、テンプレートに関連するモデルに基づいてテンプレートに名前を付けるか(/Views/DisplayTemplates/MyModel.cshtml)、またはUIHintアノテーションで明示的に強制します。
トムウェイソン、2011年

再利用可能な「ユーザーの登録」ウィザードを作成するために選択すべきアドバイスはありますか?可能であれば、これらのビュー(およびコントローラー)を別のアセンブリーに作成したいと思います。別名:これらの再利用可能なmvcフォーム/コントローラーをいくつかのチームに再配布する方法。(ユーザー/ストレージ(webapiサービス)を処理する単一の方法を作成しました...しかし、各チームは独自のmvcページを作成しています:<ありがとう
。– granadaCoder

これらのテンプレートはどこに保存しますか?それらをShared / EditorTemplatesに保存する必要がありますか、それとも現在のコントローラーフォルダーに直接保存できますか(必要な場合のみ)。
Santhos

15

あなたは確かに可能性があり、カスタマイズDisplayFor、編集可能なフォームを表示します。しかし、規則はのためであるDisplayForことreadonlyと、EditorFor編集のためにあることを。慣習に固執することで、何に渡ってDisplayForも同じタイプのことを確実に実行できます。


2
ディスプレイテンプレートとエディターテンプレートのどちらを使用すべきかについては、疑問や疑問はないと思います。本当の問題は、テンプレートとパーシャルのどちらを使うべきかということです。あなたの答えはこれを完全に逃しています。
Joshua Hayes

19
@ジョシュア-それについていくつかの質問があったと思います:「DisplayForが「読み取り専用」テンプレートをレンダリングすることも聞いたことがありますが、理解できません-フォームをそこにスローできませんでしたか?」
Robert Levy

13

私に2cの価値を与えるために、私たちのプロジェクトはいくつかのjQueryタブを持つ部分ビューを使用しており、各タブは独自の部分ビューでフィールドをレンダリングしています。一部のタブがいくつかの共通フィールドを共有する機能を追加するまで、これは問題なく機能しました。これに対する最初のアプローチは、これらの共通フィールドを使用して別の部分ビューを作成することでしたが、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と名前を正しくレンダリングします。

要するに、エディタテンプレートを使用する理由は、いくつかの共通フィールドを複数のタブに表示する必要があったからです。パーシャルビューはこのために設計されていませんが、エディターテンプレートはシナリオを完全に処理します。


1
私はタブを使用して同様の問題を持っていたあなたのためのユニークなコントロールIDを生成していますスティーブサンダーソンさんBeginCollectionItem使用して終了:blog.stevensanderson.com/2010/01/28/...
Wilkyを

1

次の_partial場合は、ビューアプローチを使用します。

  1. セントリックロジックを見る
  2. すべてを保持するもの _partialビュー関連HTMLをこのビューのみもの。テンプレートメソッドでは、「メインヘッダーや外側の境界線/設定など」のように、テンプレートビューの外側にHTMLを保持する必要があります。
  3. を使用してロジック(コントローラーから)で部分ビューをレンダリングしたいURL.Action("action","controller")

テンプレートを使用する理由:

  1. 削除したい ForEach(Iterator)。テンプレートは、モデルをリストタイプとして識別するのに十分です。自動的に行われます。
  2. モデルセントリックロジック。テンプレートフォルダーの同じディスプレイに複数のビューが見つかった場合、レンダリングは渡されたモデルに依存します。

1

これまでに言及されていないもう1つの違いは、テンプレートの場合、partialviewがモデルのプレフィックスを追加しないことです。 ここに問題があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.