連載:ASP.NET MVC入門【バージョン3対応】

第6回 テンプレート機能でビュー開発を効率化

山田 祥寛(http://www.wings.msn.to/
2011/08/19
Page1 Page2 Page3

■独自の表示/編集テンプレートを準備する

 このように、DisplayFor/EditorForヘルパーは、標準の機能を利用するだけでもそれなりに有用であるが、本当の魅力はこれからだ。あらかじめテンプレートを準備しておくことで、特定のデータ型やメタ情報に応じて、独自の出力を生成することもできる。

 例えば以下は、DateTime型のプロパティに対して、EditorForヘルパーがポップアップ・カレンダ付きのテキストボックスを生成するようにする例だ。ポップアップ・カレンダの実現には、jQuery UIのDatepickerを利用するものとする。


図2 [誕生日]欄にフォーカスを当てると、カレンダをポップアップ

[1]EditorForヘルパー向けのテンプレートを準備する

 EditorForヘルパー対応のテンプレートは、

~/Views/Shared/EditorTemplates/Xxxxx.cshtml
(VBはXxxxx.vbhtml)フォルダ配下

に配置する*1。Xxxxxの部分は、データ型、もしくはUIHint属性で指定されたビュー名を指定する(UIHint→DataType→データ型の順で検索される)。この場合であれば、DateTime型のプロパティに対してテンプレートを適用したいので、DateTime.cshtml/DateTime.vbhtmlとなるわけだ。

*1 特定のコントローラでのみ利用するテンプレートであれば、「~/Views/コントローラ名/EditorTemplate」フォルダに配置してもよい。

 具体的なコードは、以下のとおり。

@model System.DateTime

@Html.TextBoxFor(model => model, new { @class ="datepicker" })
<script type="text/javascript">
$(function () {
  $('.datepicker').datepicker();
});
</script>
@ModelType System.DateTime

@Html.TextBoxFor(Function(model) model, New With {.class = "datepicker"})
<script type="text/javascript">
$(function () {
  $('.datepicker').datepicker();
});
</script>
リスト5 DateTime型に適用するEditorForテンプレート(上:DateTime.cshtml、下:DateTime.vbhtml)

 @model/@ModelTypeディレクティブで指定されている型が「System.DateTime」となっている点に注目だ。「@Html.EditorFor(model => model.Birth)」のように呼び出している場合、テンプレートに渡されるモデルの型も(エンティティそのものの型ではなく)プロパティのDateTime型になるわけだ。

 後は渡されたモデルを基に、これまでと同じくビュー・ヘルパーを呼び出すだけだ。TextBoxForヘルパーでclass属性を付与しているのは、後からjQuery UIでdatepickerメソッドを呼び出すためのキーとするためである。datepickerメソッドは、とてもシンプルなメソッドで、「$('セレクタ').datepicker()」とすることで呼び出せる。

[2]レイアウトにJavaScript/スタイルシートを追加する

 EditorForヘルパーを利用する手順とはやや外れるが、今回は、jQuery UIを利用するために必要なJavaScript/スタイルシートをレイアウトに追加しておこう。

<head>

  ……中略……

  <link href="@Url.Content("~/Content/Site.css")"
    rel="stylesheet" type="text/css" />

  <link
    href="@Url.Content("~/Content/jquery-ui-1.8.14.custom.css")"
    rel="stylesheet" type="text/css" />


  <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
    type="text/javascript"></script>

  <script
    src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")"
    type="text/javascript"></script>

  <script
    src="@Url.Content("~/Scripts/jquery.ui.datepicker-ja.js")"
    type="text/javascript"></script>


  <script
    src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
   type="text/javascript">
</script>
</head>
リスト6 jQuery UIを有効にするためのJavaScript/スタイルシートを追加(_Layout.cshtml/_Layout.vbhtml。いずれも同じコード)

 jquery-ui-1.8.11.min.jsはjQuery UI本体、jquery.ui.datepicker-ja.jsはdatepickerを日本語化するためのデータ、そして、jquery-ui-1.8.14.custom.cssはjQuery UIのスタイルシートである。このうち、jquery-ui-1.8.11.min.jsを除いては、標準のプロジェクト・テンプレートには含まれていないので、jQuery UI本家サイトからダウンロードし、プロジェクトにインポートしておく必要がある。

 以上で自作テンプレートを利用する準備は完了だ。アプリケーションを再起動し、編集モードを開いてみよう。冒頭の図のように、[誕生日]欄にフォーカスを移動すると、ポップアップ・カレンダが表示されれば、テンプレートは正しく認識されている。

 なお、ここではEditorForヘルパーを例に紹介したが、DisplayForヘルパーでもテンプレートの配置先が、

~/Views/Shared/DisplayTemplateフォルダ

となるだけで、テンプレート自体は同じ要領で作成できる。

[参考]ビュー側で呼び出すテンプレートを決められる

 繰り返しではあるが、DisplayFor/EditorForヘルパーでは、モデル側のデータ型、メタ情報に応じて、対応するテンプレートを呼び出すのが基本だ。しかし、ビュー側で明示的に呼び出すべきテンプレートを指定したい場合もあるだろう。

 この場合は、以下のように第2引数としてビュー名を指定してやればよい。以下は、データ型やメタ情報に関わらず、「~/Views/Shared/EditorTemplate/Calendar.cshtml」を呼び出すためのコードである。

@Html.EditorFor(model => model.Birth, "Calendar")
@Html.EditorFor(Function(model) model.Birth, "Calendar")
リスト7 呼び出すべきテンプレートを明示的に指定した例

■モデル単位にテンプレートを適用する − DisplayForModel/EditorForModel −

 プロパティ単位に出力を生成するDisplayFor/EditorForヘルパーに対して、モデル単位の出力を生成するDisplayForModel/EditorForModelというヘルパーもある*2

*2 ただし、DisplayFor/EditorForヘルパーでも「@Html.EditorFor(m => m)」とすることで、モデル単位の出力を生成することは可能。

 こちらはデフォルトのままで利用することはあまりないかもしれないが、まずはテンプレートを用意しない素の挙動を確認しておこう。以下は、スキャフォールディング機能で自動生成した「Members/Edit.cshtml」「Members/Edit.vbhtml」をEditorForModelヘルパーで書き換えたコードと、その結果である(太字は追加部分、薄字は削除部分を表している)。

@using (Html.BeginForm()) {
  @Html.ValidationSummary(true)

  @Html.EditorForModel()
  <fieldset>
    <legend>Member</legend>
    ……中略……
  </fieldset>

}
@Using Html.BeginForm()
  @Html.ValidationSummary(True)

  @Html.EditorForModel()
  @<fieldset>
    <legend>Member</legend>
    ……中略……
    </fieldset>

End Using
リスト8 EditorForModelヘルパーをそのまま呼び出した例(上:Edit.cshtml、下:Edit.vbhtml)




図3 EditForModelヘルパーで自動生成された編集フォーム

 一応、最低限の出力が整形されていることは確認できるが、一般的には自動生成された出力で事足りるケースはあまりないだろう。そこで先ほどと同じくテンプレートを用意してみよう。

 テンプレートの配置先は、DisplayFor/EditorForヘルパーの場合と同じく、「~/Views/Shared」フォルダ配下のEditorTemplates/DisplayTemplatesフォルダである。ファイル名はエンティティに対応させて、(例えば)Memberエンティティに対応するテンプレートであればMember.cshtml/Member.vbhtmlとする。

 テンプレートの中身は、本来は用途に合わせてカスタマイズすべきであるが、今回はリスト8の薄字部分をほとんどそのまま流用させてもらった(テンプレートが利用されていることを確認するために、<legend>タグの中身を日本語化している)。

@model MvcTemplate.Models.Member

<fieldset>
  <legend>メンバ情報</legend>
  ……中略……
</fieldset>
@ModelType MvcTemplate.Member

<fieldset>
  <legend>メンバ情報</legend>
  ……中略……
</fieldset>
リスト9 EditorForModelヘルパーで利用するテンプレート(上:Member.cshtml、下:Member.vbhtml)

 この状態でサンプルを再起動し、編集画面を開いてみると、確かにMember.cshtml/Member.vbhtmlを使って、フォームが生成されていることが確認できる。


 INDEX
  ASP.NET MVC入門【バージョン3対応】
  第6回 テンプレート機能でビュー開発を効率化
    1.モデルを自動認識する高機能なビュー・ヘルパー(DisplayFor/EditorFor)
  2.独自の表示/編集テンプレートを準備する/モデル単位にテンプレートを適用
    3.ビュー・ヘルパーの自作/拡張メソッドとしてビュー・ヘルパーを定義
 
インデックス・ページヘ  「ASP.NET MVC入門【バージョン3対応】」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間