- テンプレートの紹介。 ( オリジナル )
- テンプレートのメタデータ。 ( オリジナル )
- 組み込みテンプレート。 ( オリジナル )
- 独自のテンプレートを作成します。 ( オリジナル )
- マスターテンプレート。 ( オリジナル )
パート1 はじめに
テンプレートの紹介
ASP.NET MVCの主な新しい革新の1つはテンプレートです。
テンプレートは、従来のASP.NETのダイナミックデータに似ています。 このタイプの既存のオブジェクトに基づいて、オブジェクトが単純なデータ(整数、10進数、文字列など)であるか、クラス代表であるかにかかわらず、システムはそれを表示または編集するためのマークアップを自動的に生成します。
Html.Display
要素を表示するために、3つの表示メソッドが使用されます(それぞれにいくつかのオーバーロードがあります)。
- 文字列ベース :<%= Html.Display( "PropertyName")%>
- 式ベース :<%= Html.DisplayFor(model => model.ProeprtyName)%>
- モデル :<%= Html.DisplayForModel()%>
最初の方法は、ViewDataと、タイプが不明なモデルの両方からのデータを表示するために使用できます。
次の方法は、主にモデルからデータを転送するために使用されます。 さらに、このメソッドを使用して、たとえば、ソースデータの値を完全に無視することができます(モデル=> someOtherValue)。
最後の方法は、現在のモデルのヘルパーです。 DisplayForModelメソッドは、DisplayFor(モデル=>モデル)エントリと同等です。
モデルを使用して例を開始しましょう。
パブリッククラス { パブリック文字列FirstName {get; セット; } パブリック文字列LastName {get; セット; } public int Age {get; セット; } }
...次にアクション:
pubilc ViewResultの詳細([DefaultValue(0)] int id) { 戻りビュー([id]に連絡); }
...そして最後に表示:
<%@ Page Language = "C#" MasterPageFile = "〜/ Views / Shared / Site.master" Inherits = "System.Web.Mvc.ViewPage"%> <asp:Content ContentPlaceHolderID = "MainContent" runat = "server"> <%= Html.DisplayForModel()%> </ asp:コンテンツ>
その結果、次のページが表示されます。

Html.editor
Html.Displayと同様に、オブジェクトを編集するためのhtmlを生成するために使用される3つのメソッドがあります。
- 文字列ベース :<%= Html.Editor( "PropertyName")%>
- 式ベース :<%= Html.EditorFor(model => model.ProeprtyName)%>
- モデル :<%= Html.EditorForModel()%>
ビューでDisplayForModelメソッドをEditorForModelに変更すると、ページは次のようになります。

ご覧のとおり、システムは文字列および整数値用のテキストボックスを生成しました。
本当に何が起こっているのですか?
MVC 2のテンプレートシステムには、いくつかの組み込みテンプレートが含まれています。
オブジェクトを表示するために、システムはリフレクションを使用してオブジェクトのすべてのプロパティを検索し、各プロパティのマークアップを生成します。
テンプレートを使用しない場合、マークアップは次のようになります。
<%foreach(ViewData.ModelMetadata.Propertiesのvar prop){%> <div class = "display-label"> <%= prop.GetDisplayName()%> </ div> <div class = "display-field"> <%= Html.Display(prop.PropertyName)%> </ div> <%}%>
現在、これは完全な実装ではないことに留意する必要があります。 ここで不足しているものを後で説明します。
これは、複雑なオブジェクトを表示するためのテンプレートの基礎です。現在のモデルのすべてのプロパティを調べ、それぞれがラベルを表示し、Html.Display()メソッドを呼び出してプロパティ値を表示します。
文字列を表示したい場合はどうなりますか? そして、次のことが起こります:
<%= Html.Encode(モデル)%>
繰り返しますが、これは実際のコードではありません。実際に起こることについては後で説明します。
テンプレートのオーバーライド
組み込みテンプレートには多くの利点がありますが、おそらく最も重要なことは、レンダリングのどこでもテンプレートを置き換えることができることです。
文字列のパターン置換の例を見てみましょう。 これを行うには、文字列を呼び出して〜/ Views / ControllerName / DisplayTemplatesフォルダーに配置する部分ビューを作成します 。

ファイルには次のように記述します。
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= Html.Encode(Model)%> <em>みなさん、こんにちは!</ em>
表示されるページを更新します。

ご覧のとおり、新しいテンプレートは自動的にセットアップされたため、すべての行を調べる必要はありませんでした。 ただし、テンプレートはAgeプロパティにも適用されます。Ageプロパティのタイプは実際には整数ですが、これについては後ほど説明します。
編集用のテンプレートを作成する必要がある場合は、 EditorTemplatesフォルダーに配置する必要があります。
パート2 ModelMetadata
モデルの概念化
ASP.NET MVC 2で導入された新しいクラスの1つは、モデルメタデータです。 このクラスは、オブジェクトを表示するために必要な情報を提供するように設計されています。 また、主にテンプレートの作成に使用されますが、メタデータはテンプレート内だけでなく常に使用可能です。
モデルとは何ですか?
ModelMetadataを使用する場合、「モデル」の定義は少しぼやけています。
前の部分のモデルをもう一度考えてみましょう。
パブリッククラス { パブリック文字列FirstName {get; セット; } パブリック文字列LastName {get; セット; } public int Age {get; セット; } }
このモデル用に厳密に型指定されたビューを作成しました。 このビューでViewData.ModelMetadataを参照する場合、この場合のモデルはContactクラスのオブジェクトになります。
ただし、メタデータオブジェクトを使用すると、オブジェクトのすべてのプロパティに関する情報を取得できます。 各プロパティのModelMetadataオブジェクトのコレクションを取得できます。 この例のコンテキストでは、FirstName、LastName、Ageの3つの新しいメタオブジェクトを取得します。 FirstNameプロパティのメタデータを見ると、モデルのデータ型がstringであり、コンテナオブジェクトの型がContactであることがわかります。 したがって、複雑なオブジェクトのすべてのプロパティを再帰的に繰り返すことができます。
ModelMetadataはどこで入手できますか?
現在のモデルを使用します。
メタデータにアクセスする最も簡単な方法は、ViewDataプロパティを使用することです。 この場合、ModelMetadataはViewDataに表示されるモデルを記述します。 オブジェクトのテンプレートをレンダリングする場合、このメソッドは最も簡単です。
すでにあるメタデータプロパティの1つを取得します。
既にメタデータオブジェクトがある場合は、Propertiesプロパティを使用できます。これにより、各プロパティのModelMetadataオブジェクトのリストが返されます。
式を使用する
ModelMetadataクラスには、FromStringExpressionとFromLambdaExpressionの2つの静的メソッドがあります。 これらのメソッドは、式から対応するメタデータを取得するときに使用されます(たとえば、「PropertyName」または「m => m.PropertyName」)。 ほとんどの既存のHTMLヘルパーは、これらの2つのメソッドの一部として既に書き直されています。
彼らは何を持っていますか?
ModelMetadataの操作方法について説明する前に、ModelMetadataクラスのオブジェクトが提供する情報を見てみましょう。
モデルとそのコンテナに関連するプロパティ:
- モデルとModelType
モデルとモデルタイプを返します。 また、値がnullの場合もありますが、データ型を見つけることができます。
- ContainerTypeおよびPropertyName
問題のプロパティを含むオブジェクトのタイプとプロパティの名前を返します。 すべてではない
モデルはプロパティを表すため、これらのプロパティにはnullが含まれる場合があります。
- 物性
現在のモデルのプロパティを記述するModelMetadataオブジェクトのコレクションを取得します。
モデルのメタデータ
- ConvertEmptyStringToNull
クライアントから受け取った空の文字列をnullに変換するかどうかを示すフラグ。
デフォルト:true - DataTypeName
データ型に関する情報を取得するために使用できる文字列(たとえば、現在の文字列が電子メールアドレスかどうかを確認するため)。 一般的に使用されるデータ型名は、EmailAddress、Html、Password、およびUrlです。
デフォルト:null - 説明
モデルの説明。
デフォルト:null - DisplayFormatString
テンプレートにモデル値を表示するための形式。
デフォルト:null - 表示名
モデルの表示名。
デフォルト:null - EditFormatString
テンプレートの値を編集するために使用される文字列の形式。
デフォルト:null - HideSurroundingHtml
現在のフィールドにhtmlタグ(ラベルなど)を付けないことを示すフラグ。 多くの場合、「非表示」フィールドの生成に使用されます
デフォルト:false - IsComplexType
システムを複合型として処理する(したがって、複合型にテンプレートを使用する)か、単純型(たとえば、文字列)として処理するかを示すフラグ。
ユーザーはインストールされていません。 - IsNullableValueType
型がNullable型であるかどうかを示すフラグ/
ユーザーはインストールされていません。 - IsReadOnly
このプロパティが読み取り専用であることを示すフラグ。
デフォルト:false - 必須
プロパティは必要ですか?
デフォルト:null不可型の場合はtrue。 それ以外の場合はfalse。 - NullDisplayText
モデルがnullの場合に表示されるテキスト。
デフォルト:null - ShortDisplayName
現在のモデルの短い名前。 テーブルヘッダーで使用するために設計されています。 このプロパティが設定されていない場合、DisplayNameプロパティが使用されます。
デフォルト:null - ShowForDisplay
現在のモデルを表示に使用する必要があります。
デフォルト:true - ShowForEdit
現在のモデルを編集に使用すべきか
デフォルト:true - SimpleDisplayText
合計行の特定のモデルに表示されるテキスト。 それ以外の場合は、複雑なオブジェクトの表示が使用されます。
デフォルト:以下を参照 - TemplateHint
モデルに使用されるヒント。
デフォルト:null - 透かし
編集時に入力行にヒントとして表示できるテキスト。
デフォルト:null
方法
- GetDisplayName()
このメソッドは、モデル名を取得するために使用できます。 DisplayNameプロパティがnullでない場合、値を返します。 PropetyNameがnullでない場合、それを返します。 それ以外の場合は、ModelType.Nameを返します。 - GetValidators()
このメソッドは、このモデルのバリデーターを取得するために使用されます。 サーバー検証とクライアント検証ルールの生成の両方に使用できます。
SimpleDisplayTextのデフォルト値は、次の規則に従います。
- Modelがnullの場合、NullDisplayTextが返されます
- ToStringモデルメソッドにオーバーロードがある場合、その呼び出しの結果が返されます。
- モデルにプロパティがない場合、String.Emptyが返されます
- モデルの最初のプロパティがnullの場合、NullDisplayTextが返されます
- それ以外の場合、最初のプロパティのToString()が返されます。
ModelMetadataはどのように形成されますか?
ASP.NET MVC 2にカスタムメタデータシステムを追加しました。デフォルトでは、メタオブジェクトは属性から取得したデータに基づいて形成されます。
次の属性を使用して、メタデータモデルを形成します。
- [HiddenInput](System.Web.Mvc)
この属性でマークされたプロパティは、編集モードで「非表示」フィールドを生成します。 デフォルトでは、この場合も付随するhtmlタグは使用されません。 DisplayValueフラグをtrueに設定すると、付随するhtmlおよび「hidden」フィールドが生成されます。 さらに、この場合、TemplateHintプロパティが設定されます([UIHint]属性によってオーバーライドされる場合があります)
- [UIHint](System.ComponentModel.DataAnnotations)
TemplateHintプロパティを設定します。
- [データ型](System.ComponentModel.DataAnnotations)
DataTypeNameプロパティを設定します。
- [読み取り専用](System.ComponentModel)
IsReadOnlyプロパティを設定します。 セッターのないプロパティには、[ReadOnly]属性が自動的にタグ付けされることに注意してください。
- [DisplayFormat](System.ComponentModel.DataAnnotations)
この属性を使用して、メタデータにNullDisplayTextを設定できます。 属性プロパティDataFormatStringを設定すると、メタデータのDisplayFormatStringプロパティに適用されます。 ApplyFormatInEditMode属性の属性プロパティをtrueに設定すると、EditFormatStringにも適用されます。 ConvertEmptyStringToNullプロパティを設定すると、ConvertEmptyStringToNullメタデータプロパティに影響します。
- [ScaffoldColumn](System.ComponentModel.DataAnnotations)
ShowForDisplayおよびShowForEditプロパティが設定されます。
- [DisplayName](System.ComponentModel)
DisplayNameプロパティに使用されます。
パート3。 組み込みテンプレート。
テンプレートアプローチ
組み込みテンプレートについて説明する前に、作業でのテンプレートの使用方法と、テンプレートを直接オーバーラップする方法について説明します。
パス
使用するテンプレートが決定されると、システムはいくつかのパスを調べます。 それぞれについて、必要な結果に応じて、「DisplayNames / TemplateName」または「EditorName / TemplateName」という名前のascxファイルを検索します。
検索は次の順序で実行されます。
- 〜/ Areas / AreaName / Views / ControllerName / DisplayTemplates / TemplateName.aspxおよび.ascx
- 〜/ Areas / AreaName / Views / Shared / DisplayTemplates / TemplateName.aspxおよび.ascx
- 〜/ビュー/ ControllerName / DisplayTemplates / TemplateName.aspxおよび.ascx
- 〜/ビュー/共有/ DisplayTemplates / TemplateName.aspxおよび.ascx
(テンプレートを編集するには、DisplayTemplatesをEditorTemplatesに置き換えます。)
パターン名
テンプレート名は次の順序で検索されます。
- ModelMetadataオブジェクトのTemplateHintプロパティの値
- ModelMetadataオブジェクトのDataTypeNameプロパティの値
- タイプ名。
- オブジェクトが単純型の場合、「String」
- オブジェクトが複合型およびインターフェースの場合、「オブジェクト」
- オブジェクトがインターフェイスではなく複合型である場合、ネストされたプロパティの階層全体を通じて再帰的に、各プロパティの名前を取得しようとします
タイプ名で検索する場合、名前空間のない単純な名前(Type.Nameなど)を意味します。 さらに、タイプがNullable <T>の場合、タイプTに対して検索が実行されます(つまり、ブールパターンは「bool」と「Nullable <bool>」の両方に使用されます)。 つまり、値型のテンプレートを作成している場合は、その型がNULL可能かどうかを考慮する必要があります。 以下は、ブール型の組み込みテンプレートを使用した例です。
クラスTemplateInfo
そして、実装を詳しく調べる前に言及する価値のある最後のものはTemplateInfoクラスです。 TemplateInfoは、モデルメタデータとは異なり、ViewDataから常にアクセスできるとは限りません。テンプレートにいる場合のみです。
TemplateInfoで使用される主なプロパティはFormattedModelValueです。 このフィールドの値は、モデルの文字列としての正しい形式の値(ModelMetadataで指定された形式に基づく)、またはモデルの元の値(文字列の形式が指定されていない場合)のいずれかです。
さらに使用するものがいくつかあります(TemplateDepthプロパティやVisitedメソッドなど)。 しかし、私はそれらを理解するにつれて、それらの意味を説明します。
組み込みの表示テンプレート
システムがデータを表示するために使用するテンプレート名は9つあります:「ブール」、「10進数」、「EmailAddress」、「HiddenInput」、「Html」、「オブジェクト」、「ストリング」、「テキスト」および「Url」 それらの2つ(「テキスト」と「文字列」)は等しく実装されています。 それらの一部には、テンプレートを編集するための対応する類似物がありますが、一部はありません。
ASP.NET MVCの組み込みテンプレートはコードに実装されていますが、例として、.ascxファイルの機能を書き直しました。 これにより、それらをよりよく理解でき、これらのテンプレートの独自のバージョンを簡単に作成できます。
DisplayTemplate / String.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%>
驚きはありません。モデルを表示するだけで、その中の特別なhtml文字を置き換えます。
DisplayTemplates / Html.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= ViewData.TemplateInfo.FormattedModelValue%>
このテンプレートは、「Html」タイプがコンテンツがhtmlであり、したがってエンコードされてはならないことを意味するため、前のテンプレートよりも少し単純です。 XSS攻撃を避けるために、エンドユーザーからデータを受信する場合、このタイプを使用する場合は注意してください!
DisplayTemplates / EmailAddress.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <a href="mailto:<%= Html.AttributeEncode(Model) %> "> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%> </a>
このテンプレートは、モデルがメールアドレスであると想定し、モデルへのリンクを自動的に作成します。 モデルは電子メールアドレスに使用され、FormattedModelValueは表示に使用されることに注意してください。
DisplayTemplates / Url.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <a href="mailto:<%= Html.AttributeEncode(Model) %> "> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%> </a>
前の例のように機能します。
DisplayTemplates / HiddenInput.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%if(!ViewData.ModelMetadata.HideSurroundingHtml){%> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%> <%}%>
このテンプレートは、上記の[HiddenInput]属性と組み合わせて使用されます。 ユーザーがHideSurroundHtmlプロパティを明示的に指定していない場合にのみ、表示値を生成します。
DisplayTemplates / Decimal.ascx
<%@ control language = "C#" inherits = "System.Web.Mvc.ViewUserControl"%> <script runat = "server"> プライベートオブジェクトFormattedValue { 得る { if(ViewData.TemplateInfo.FormattedModelValue == ViewData.ModelMetadata.Model) { return String.Format(System.Globalization.CultureInfo.CurrentCulture、 "{0:0.00}"、ViewData.ModelMetadata.Model); } return ViewData.TemplateInfo.FormattedModelValue; } } </ script> <%= Html.Encode(FormattedValue)%>
このテンプレートは主に通貨表現に使用されるため、このテンプレートは小数点以下2桁の10進数値を表示します。 そのようなフォーマットの状態に注意してください。
DisplayTemplates / Boolean.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <script runat = "server"> プライベートブール? ModelValue { 得る { ブール? 値= null; if(ViewData.Model!= null) { 値= Convert.ToBoolean(ViewData.Model、System.Globalization.CultureInfo.InvariantCulture); } 戻り値; } } </ script> <%if(ViewData.ModelMetadata.IsNullableValueType){%> <select class = "list-box tri-state" disabled = "disabled"> <オプション値= "" <%= ModelValue.HasValue? "": "selected = 'selected'"%>> 設定なし</ option> <オプション値= "true" <%= ModelValue.HasValue && ModelValue.Value? "selected = 'selected'": ""%>> True </ option> <オプション値= "false" <%= ModelValue.HasValue &&!ModelValue.Value? "selected = 'selected'": ""%>> 偽</ option> </ select> <%} else {%> <input class = "check-box" disabled = "disabled" type = "checkbox" <%= ModelValue.Value? "checked = 'checked'": ""%> /> <%}%>
ブール型のテンプレートは、型がNULL入力可能かどうかに応じてマークアップを生成する必要があるという点で興味深いです。 null不可の場合、通常のチェックボックスが使用されます。そうでない場合、3つの値を持つドロップダウンリストが表示されます。
DisplayTemplates / Object.ascx
あなたに代わって多くの作業が行われているため、コードを見る前にこのテンプレートのロジックを説明する価値があります。
オブジェクトタイプのテンプレートの主な目標は、それぞれのHTMLマークアップとともに、複雑なオブジェクトのすべてのプロパティです。 さらに、NullDisplayTextモデルの値がnullの場合、その値を表示する責任があります。 そして、それはいわゆる「シャローダイブ」を提供し、必要なレベルのプロパティのみを表示します。 後ほど、このテンプレートの設定について説明します。これには、ディープダイブ操作の準備も含まれます。
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%if(Model == null){%> <%= ViewData.ModelMetadata.NullDisplayText%> <%} else if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} else {%> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForDisplay &&!ViewData.TemplateInfo.Visited(pm))){%> <%if(prop.HideSurroundingHtml){%> <%= Html.Display(prop.PropertyName)%> <%} else {%> <%if(!String.IsNullOrEmpty(prop.GetDisplayName())){%> <div class = "display-label"> <%= prop.GetDisplayName()%> </ div> <%}%> <div class = "display-field"> <%= Html.Display(prop.PropertyName)%> </ div> <%}%> <%}%> <%}%>
この例をもっと詳しく見てみましょう。
<%if(Model == null){%> <%= ViewData.ModelMetadata.NullDisplayText%> <%}
この場所ではすべてが明確であり、モデルがnullの場合はNullDisplayTextが表示されます。
else if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%}
この時点で、プロパティのネストのレベルを制限します(「浅いダイビング」、浅いダイビング)。 TemplateInfoクラスは、テンプレートのネストの深さを追跡します。 トップレベルのTemplateDepthプロパティは1です。
その他{%> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForDisplay &&!ViewData.TemplateInfo.Visited(pm))){%>
これは、オブジェクトのプロパティを通るメインループです。 表示すべきでないことを示すプロパティは無視されます。 プロパティフィルターの別の部分は、無限再帰を防ぐために、このオブジェクトが以前にレンダリングされたかどうかをTemplateInfoに尋ねます。
<%if(prop.HideSurroundingHtml){%> <%= Html.Display(prop.PropertyName)%> <%}
このプロパティがtrueに設定されている場合、テンプレートは、不必要なhtmlマークアップなしで、表示するようプロパティに要求するだけです。
<%if(!String.IsNullOrEmpty(prop.GetDisplayName())){%> <div class = "display-label"> <%= prop.GetDisplayName()%> </ div> <%}%> <div class = "display-field"> <%= Html.Display(prop.PropertyName)%> </ div>
この時点で、プロパティに表示名があるかどうかが確認され、表示名がある場合はdivで囲まれて表示されます。 次に、プロパティのレンダリングが開始されます。
組み込みの編集テンプレート
編集テンプレートは、値を編集する機能が含まれているため、表示テンプレートよりも少し複雑です。 既存のHTMLヘルパーの上に構築されます。 合計で7つの編集テンプレートがあります:「ブール」、「10進数」、「非表示入力」、「マルチラインテキスト」、「オブジェクト」、「パスワード」、「ストリング」。
多くの場合、htmlヘルパーの要素名として空の文字列が渡されます。 これは通常間違っていますが、テンプレートの場合、プロパティの「コンテキスト」があります。 これにより、ネストプロパティの階層(「Contact.HomeAddress.City」など)を維持できるため、複雑なオブジェクトを操作しやすくなります。
名前をhtmlヘルパーに渡すと、「City」というオブジェクトのプロパティを編集するためのテキストボックスをください。 しかし、テンプレートが住所用ではなく、複雑なオブジェクトではなく、都市用であり、文字列用である場合はどうなりますか? 空の文字列を名前として渡すと、htmlヘルパーに「自分で編集するためのテキストボックスをください」と伝えます。
EditorTemplates / String.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= Html.TextBox( ""、ViewData.TemplateInfo.FormattedModelValue、 新しい{@class = "text-box single-line"})%>
繰り返しますが、これは理解しやすい最も簡単なテンプレートなので、行から始めましょう。 このテンプレートは、システムにテキストボックス(それ自体を編集するため)を取得したいことを伝え、編集されたプロパティのフォーマットされた値で開始します。 さらに、このテキストボックスには、2つのCSSクラス「text-box」と「single-line」を使用します。
EditorTemplates / Password.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= Html.Password( ""、ViewData.TemplateInfo.FormattedModelValue、 新しい{@class = "テキストボックスの単一行パスワード"})%>
パスワードを入力するためのパターンは、パスワードヘルパーメソッドを呼び出して別のCSSクラス(「パスワード」)を使用することを除いて、文字列のパターンに似ています。
EditorTemplates / MultilineText.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%= Html.TextArea( ""、ViewData.TemplateInfo.FormattedModelValue.ToString()、 0、0、新規{@class = "text-box multi-line"})%>
繰り返しますが、驚きはありません。 TextAreaメソッドを呼び出して、0に等しい行と列の数を指定し(CSSを使用するため)、クラス「single-line」の代わりにクラス「multi-line」を使用します。
EditorTemplates / HiddenInput.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <script runat = "server"> プライベートオブジェクトModelValue { 得る { if(モデルはSystem.Data.Linq.Binary) { return Convert.ToBase64String(((System.Data.Linq.Binary)Model).ToArray()); } if(モデルはバイト[]) { return Convert.ToBase64String((byte [])Model); } モデルを返す; } } </ script> <%if(!ViewData.ModelMetadata.HideSurroundingHtml){%> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%> <%}%> <%= Html.Hidden( ""、ModelValue)%>
ご覧のとおり、表示テンプレートよりもはるかに複雑です。 ModelValueプロパティは、モデルがバイト配列かバイナリlinq2sqlオブジェクトかを判断し、base64を使用して文字列に変換します。 次に、結果を非表示フィールドに書き込みます。
EditorTemplates / Decimal.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <script runat = "server"> プライベートオブジェクトModelValue { 得る { if(ViewData.TemplateInfo.FormattedModelValue == ViewData.ModelMetadata.Model) { return String.Format(System.Globalization.CultureInfo.CurrentCulture、 「{0:0.00}」、ViewData.ModelMetadata.Model); } return ViewData.TemplateInfo.FormattedModelValue; } } </ script> <%= Html.TextBox( ""、ModelValue、new {@class = "text-box single-line"})%>
Decimalのテンプレートは、表示用の対応するテンプレートに似ていますが、編集用のテキストボックスが生成される点が異なります。
EditorTemplates / Boolean.ascx
<%@ control language = "C#" inherits = "System.Web.Mvc.ViewUserControl"%> <script runat = "server"> プライベートリスト<SelectListItem> TriStateValues { 得る { 新しいリスト<SelectListItem>を返す{ 新しいSelectListItem {Text = "Not Set"、 値= String.Empty、 選択=!Value.HasValue}、 新しいSelectListItem {Text = "True"、 値= "true"、 選択= Value.HasValue && Value.Value}、 新しいSelectListItem {Text = "False"、 値= "false"、 選択= Value.HasValue &&!Value.Value}、 }; } } プライベートブール? 価値 { 得る { ブール? 値= null; if(ViewData.Model!= null) { 値= Convert.ToBoolean(ViewData.Model、 System.Globalization.CultureInfo.InvariantCulture); } 戻り値; } } </ script> <%if(ViewData.ModelMetadata.IsNullableValueType){%> <%= Html.DropDownList( ""、TriStateValues、new {@class = "list-box tri-state"})%> <%} else {%> <%= Html.CheckBox( ""、Value ?? false、new {@class = "check-box"})%> <%}%>
このテンプレートは、表示用の対応するテンプレートにも似ています。
EditorTemplates / Object.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} その他{%> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForEdit &&!ViewData.TemplateInfo.Visited(pm))){%> <%if(prop.HideSurroundingHtml){%> <%= Html.Editor(prop.PropertyName)%> <%} else {%> <%if(!String.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())){%> <div class = "editor-label"> <%= Html.Label(prop.PropertyName)%> </ div> <%}%> <div class = "editor-field"> <%= Html.Editor(prop.PropertyName)%> <%= Html.ValidationMessage(prop.PropertyName、 "*")%> </ div> <%}%> <%}%> <%}%>
同様に、このテンプレートはあまり変更されておらず、ValidationMessageメソッドへの呼び出しのみが追加されています。
パート4。 独自のテンプレートを作成する
さらに例として、次のモデル、コントローラー、およびプレゼンテーションが使用されます。
モデル/ SampleModel.cs
System.ComponentModel.DataAnnotationsを使用します。 System.Web.Mvcを使用します。 パブリッククラスSampleModel { public static SampleModel Create() { 新しいSampleModelを返す { ブール= true EmailAddress = "admin@contoso.com"、 10進数= 21.1234M、 整数= 42、 非表示=「編集不可」、 HiddenAndInvisible = "編集不可"、 Html = "これは<b> HTML </ b>対応です"、 MultilineText = "この\ r \ nhas \ r \ nmultiple \ r \ nlines"、 NullableBoolean = null、 パスワード= "supersecret"、 文字列=「単純な文字列」、 Url = "http://www.microsoft.com/"、 }; } public boolブール値{get; セット; } [DataType(DataType.EmailAddress)] パブリック文字列EmailAddress {get; セット; } public decimal Decimal {get; セット; } [HiddenInput] パブリックストリングHidden {get; セット; } [HiddenInput(DisplayValue = false)] パブリック文字列HiddenAndInvisible {get; セット; } [DataType(DataType.Html)] パブリックストリングHtml {get; セット; } [必須] [範囲(10、100)] public int Integer {get; セット; } [DataType(DataType.MultilineText)] パブリックストリングMultilineText {get; セット; } パブリックブール? NullableBoolean {get; セット; } [DataType(DataType.Password)] パブリックストリングパスワード{get; セット; } public string String {get; セット; } [DataType(DataType.Url)] パブリック文字列Url {get; セット; } [DisplayFormat(NullDisplayText = "(null value)")] public ChildModel ChildModel {get; セット; } }
モデル/ ChildModel.cs
System.ComponentModel.DataAnnotationsを使用します。 [DisplayColumn( "FullName")] パブリッククラスChildModel { [必須、StringLength(25)] パブリック文字列FirstName {get; セット; } [必須、StringLength(25)] パブリック文字列LastName {get; セット; } [ScaffoldColumn(false)] パブリックストリングFullName { 得る { Return FirstName + "" + LastName; } } }
コントローラー/ HomeController.cs
System.Web.Mvcを使用します。 パブリッククラスHomeController:コントローラー { static SampleModel model = SampleModel.Create(); パブリックViewResultインデックス() { 戻りビュー(モデル); } パブリックViewResult編集() { 戻りビュー(モデル); } [HttpPost] [ValidateInput(false)] パブリックActionResult編集(SampleModelを編集したモデル) { if(ModelState.IsValid) { モデル= editedModel; return RedirectToAction( "詳細"); } Return View(editedModel); } }
ビュー/ホーム/ Index.aspx
<%@ Page Language = "C#" MasterPageFile = "〜/ Views / shared / Site.master" Inherits = "ViewPage <SampleModel>"%> <asp:Content ContentPlaceHolderID = "MainContent" runat = "server"> <h3>詳細</ h3> <fieldset style = "padding:1em; margin:0; border:solid 1px#999;"> <%= Html.DisplayForModel()%> </ fieldset> <p> <%= Html.ActionLink( "編集"、 "編集")%> </ p> </ asp:コンテンツ>
ビュー/ホーム/ Edit.aspx
<%@ Page Language = "C#" MasterPageFile = "〜/ Views / shared / Site.master" Inherits = "ViewPage <SampleModel>"%> <asp:コンテンツID = "Content2" ContentPlaceHolderID = "MainContent" runat = "server"> <h3>編集</ h3> <%using(Html.BeginForm()){%> <fieldset style = "padding:1em; margin:0; border:solid 1px#999;"> <%= Html.ValidationSummary( "壊れたもの:")%> <%= Html.EditorForModel()%> <入力タイプ= "送信"値= "送信" /> </ fieldset> <%}%> <p> <%= Html.ActionLink( "Details"、 "Index")%> </ p> </ asp:コンテンツ>
デフォルトの表示テンプレート
デフォルトのテンプレートを使用してアプリケーションを実行すると、次のページが表示されます。

編集用のページは次のようになります。

テーブルを使用します
名前と値のペアが1行で表示されるように、マークアップをテーブル形式で作成しましょう。 編集用のテンプレートには、必須フィールドにアスタリスクが表示されることに注意してください。
ビュー/共有/ DisplayTemplates / Object.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%if(Model == null){%> <%= ViewData.ModelMetadata.NullDisplayText%> <%} else if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} else {%> <table cellpadding = "0" cellspacing = "0" border = "0"> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForDisplay &&!ViewData.TemplateInfo.Visited(pm))){%> <%if(prop.HideSurroundingHtml){%> <%= Html.Display(prop.PropertyName)%> <%} else {%> <tr> <td> <div class = "display-label" style = "text-align:right;"> <%= prop.GetDisplayName()%> </ div> </ td> <td> <div class = "display-field"> <%= Html.Display(prop.PropertyName)%> </ div> </ td> </ tr> <%}%> <%}%> </ table> <%}%>
その結果、次のフォームを取得します。

ビュー/共有/ EditorTemplates / Object.ascx
<%@ Control Language = "C#" Inherits = "System.Web.Mvc.ViewUserControl"%> <%if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} else {%> <table cellpadding = "0" cellspacing = "0" border = "0"> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForEdit &&!ViewData.TemplateInfo.Visited(pm))){%> <%if(prop.HideSurroundingHtml){%> <%= Html.Editor(prop.PropertyName)%> <%} else {%> <tr> <td> <div class = "editor-label" style = "text-align:right;"> <%= prop.IsRequired? "*": ""%> <%= Html.Label(prop.PropertyName)%> </ div> </ td> <td> <div class = "editor-field"> <%= Html.Editor(prop.PropertyName)%> <%= Html.ValidationMessage(prop.PropertyName、 "*")%> </ div> </ td> </ tr> <%}%> <%}%> </ table> <%}%>
したがって、次のマークアップを作成しました。

浅いダイビングと深いダイビング(浅いダイビングと深いダイビング)
上記のスクリーンショットでは、ChildModelは(null値)と表示されています。これは、コードの属性を使用してこの値を設定しているためです。
編集モードであっても、このプロパティを変更することはできません。
最初の「if」条件を削除して編集テンプレートを変更すると、次のようになります。

表示モードでは:

表示用のテンプレートを変更していないため、「shallow dive」(shallow dive)のロジックで結果が得られます。 モデルの[DisplayColumn]属性を使用し、FullNameプロパティを表示するように指定したため、フルネームが表示されます。
。
表示テンプレートを変更してディープダイブを使用すると、次の結果が得られます。

パート5 MasterPageテンプレート
最初に行う必要があるのは、テンプレートで使用されるMasterPageを定義することです。1つは編集テンプレート用で、もう1つは表示テンプレート用です。
DisplayTemplates / Template.master
<%@ Master Language = "C#" Inherits = "System.Web.Mvc.ViewMasterPage"%> <script runat = "server"> 保護されたオーバーライドvoid OnInit(EventArgs e){ base.OnInit(e); if(ViewData.ModelMetadata.HideSurroundingHtml){ TablePlaceholder.Visible = false; } その他{ Controls.Remove(データ); DataPlaceholder.Controls.Add(データ); } } </ script> <asp:ContentPlaceHolder runat="server" id="Data" /> <asp:PlaceHolder runat="server" id="TablePlaceholder"> <table cellpadding="0" cellspacing="0" border="0" width="100%"> <tr> <td style="width: 10em;"> <div class="display-label" style="text-align: right;"> <asp:ContentPlaceHolder runat="server" id="Label"> <%= ViewData.ModelMetadata.GetDisplayName() %> </asp:ContentPlaceHolder> </ div> </ td> <td> <div class="display-field"> <asp:PlaceHolder runat="server" id="DataPlaceholder" /> </ div> </ td> </ tr> </ table> </asp:PlaceHolder>
このページの動作の本質は、「ラベル」と「データ」と呼ばれる2つのContentPlaceHolderを定義することです。コンテンツ「Label」には、プロパティの名前と「Data」の値がそれぞれ表示されます。
このテンプレートは、Webフォームの1つの機能を使用します。OnInitメソッドでは、モデルにhtmlマークアップを使用するかどうかに応じて、ページを再編成します。
EditorTemplates / Template.master
<%@ Master Language = "C#" Inherits = "System.Web.Mvc.ViewMasterPage"%> <script runat = "server"> 保護されたオーバーライドvoid OnInit(EventArgs e){ base.OnInit(e); if(ViewData.ModelMetadata.HideSurroundingHtml){ TablePlaceholder.Visible = false; } その他{ Controls.Remove(データ); DataPlaceholder.Controls.Add(データ); } } </ script> <asp:ContentPlaceHolder runat="server" id="Data" /> <asp:PlaceHolder runat="server" id="TablePlaceholder"> <table cellpadding="0" cellspacing="0" border="0" width="100%"> <tr> <td style="width: 10em;"> <asp:ContentPlaceHolder runat="server" id="Label"> <div class="editor-label" style="text-align: right;"> <%= ViewData.ModelMetadata.IsRequired ? "*" : "" %> <%= Html.Label("") %> </ div> </asp:ContentPlaceHolder> </ td> <td> <div class="editor-field"> <asp:PlaceHolder runat="server" id="DataPlaceholder" /> <asp:ContentPlaceHolder runat = "server" ID = "Validation"> <%= Html.ValidationMessage( ""、 "*")%> </ asp:ContentPlaceHolder> </ div> </ td> </ tr> </ table> </ asp:PlaceHolder>
編集用のテンプレートのバージョンは、バリデータメッセージ用に設計された3番目のプレースホルダーがあり、必須フィールドにマークが付けられている点でのみ異なります。
パターンを使用した単純型
単純型では、<asp:Content ...>サーバータグを使用してマスターテンプレートを使用します。
DisplayTemplates / String.aspx
<%@ Page Language = "C#" MasterPageFile = "Template.Master" Inherits = "System.Web.Mvc.ViewPage"%> <asp:Content ContentPlaceHolderID = "Data" runat = "server"> <%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue)%> </ asp:コンテンツ>
EditorTemplates / String.aspx
<%@ Page Language = "C#" MasterPageFile = "Template.Master" Inherits = "System.Web.Mvc.ViewPage"%> <asp:Content ContentPlaceHolderID = "Data" runat = "server"> <%= Html.TextBox( ""、ViewData.TemplateInfo.FormattedModelValue、 新しい{@class = "text-box single-line"})%> </ asp:コンテンツ>
複合型テンプレート
複合型のテンプレートは、マスターテンプレートの一般的なマークアップを削除したため、はるかに単純になりました。残るのはロジックだけです。
DisplayTemplates / Object.aspx
<%@ Page Language = "C#" Inherits = "System.Web.Mvc.ViewPage"%> <%if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} else {%> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForDisplay &&!ViewData.TemplateInfo.Visited(pm))){%> <%= Html.Display(prop.PropertyName)%> <%}%> <%}%>
EditorTemplates / Object.aspx
<%@ Page Language = "C#" Inherits = "System.Web.Mvc.ViewPage"%> <%if(ViewData.TemplateInfo.TemplateDepth> 1){%> <%= ViewData.ModelMetadata.SimpleDisplayText%> <%} else {%> <%foreach(ViewData.ModelMetadata.Properties.Whereのvar prop(pm => pm.ShowForEdit &&!ViewData.TemplateInfo.Visited(pm))){%> <%= Html.Editor(prop.PropertyName)%> <%}%> <%}%>
これらのテンプレートでは、マークアップがなく、ロジックのみがあるため、MasterPageを使用しないことに注意してください。単純型のテンプレートを呼び出すと、マークアップが生成されます。
おわりに
ASP.NET MVC 2はまだベータ版であり、リリースにより変更される可能性があります。ただし、主要なポイントは説明どおりに正確に維持され、この資料をマスターしたことで、最終バージョンのリリースに向けた準備が整います。