前回は、ASP.NET MVC 3で搭載された新たなビュー・エンジン「Razor」と、ビュー開発で利用できる主なビュー・ヘルパーについて解説した。ASP.NET MVCでは、Webフォームのようなサーバ・コントロールこそ利用できないものの、ビュー・ヘルパーを活用することで、ビュー開発をかなりの程度まで効率化できる。
今回も前回に引き続き、ビュー・ヘルパーの話題だ。前回扱えなかったビュー・ヘルパーとして、DisplayFor/EditorFor、DisplayForModel/EditorForModelヘルパーについて解説するとともに、記事後半では、ビュー・ヘルパーの自作についても扱う。
モデルを自動認識する高機能なビュー・ヘルパー − DisplayFor/EditorFor −
DisplayFor/EditorForヘルパーは、いうなれば、モデル定義に応じて出力を自在に変化できるヘルパーだ。DisplayForヘルパーはデータ表示を、EditorForヘルパーはデータ編集(入力)項目の生成を担う。
“モデル定義に応じて”とは、もっといえば、モデルが持つプロパティのデータ型や付随するメタ情報に応じて、適切なタグを生成するということ。具体的には、(例えば)プロパティの型がstring型であればEditorForメソッドはテキストボックスを生成するが、bool型であればチェック・ボックス(または選択ボックス)を生成する、といった具合だ。
モデルの状態をヘルパーが自動認識してくれるため、モデルの変更がビューに影響を及ぼさない(及ぼしにくい)のがDisplayFor/EditorForメソッドのよいところである。スキャフォールディング機能が自動生成するビュー・テンプレートも、DetailsFor/EditorForヘルパーにより記述されている。
■DisplayFor/EditorForヘルパーの基本的な挙動
概要だけでは分かりにくいと思うので、まずは、DisplayFor/EditorForメソッドの標準的な動きを見てみよう。
エンティティとしては、あらかじめ以下のようなMember/Messageエンティティを、また、対応するコンテキスト・クラスも定義しておこう(また、接続設定として、第2回のリスト4のようなコードが定義されているものとする)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace MvcTemplate.Models
{
public class Member
{
public int MemberId { get; set; } // メンバーコード(主キー)
[DisplayName("名前")]
public string Name { get; set; } // 名前
[DisplayName("パスワード")]
[DataType(DataType.Password)]
public string Password { get; set; } // パスワード
[DisplayName("誕生日")]
[DisplayFormat(DataFormatString="{0:yyyy年MM月dd日}")]
public DateTime Birth { get; set; } // 誕生日
[DisplayName("メールアドレス")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; } // メール・アドレス
[DisplayName("URL")]
[DataType(DataType.Url)]
public string Url { get; set; } // URL
[DisplayName("紹介文")]
[DataType(DataType.MultilineText)]
public string Info { get; set; } // 詳細情報
[DisplayName("メッセージ")]
public virtual ICollection<Message> Messages { get; set; } // メッセージ
}
}
|
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
Public Class Member
Public Property MemberId As Integer ' メンバーコード(主キー)
<DisplayName("名前")>
Public Property Name As String ' 名前
<DisplayName("パスワード")>
<DataType(DataType.Password)>
Public Property Password As String ' パスワード
<DisplayName("誕生日")>
<DisplayFormat(DataFormatString:="{0:yyyy年MM月dd日}")>
Public Property Birth As DateTime ' 誕生日
<DisplayName("メールアドレス")>
<DataType(DataType.EmailAddress)>
Public Property Email As String ' メール・アドレス
<DisplayName("URL")>
<DataType(DataType.Url)>
Public Property Url As String ' URL
<DisplayName("紹介文")>
<DataType(DataType.MultilineText)>
Public Property Info As String ' 詳細情報
<DisplayName("メッセージ")>
Public Overridable Property Messages As ICollection(Of Message) ' メッセージ
End Class
|
|
リスト1 メンバ情報を表すMemberエンティティ(上:Member.cs、下:Member.vb) |
using System.ComponentModel.DataAnnotations;
namespace MvcTemplate.Models
{
[DisplayColumn("Body")]
public class Message
{
public int MessageId { get; set; } // メッセージID(主キー)
public string Body { get; set; } // メッセージ本体
}
}
|
Imports System.ComponentModel.DataAnnotations
<DisplayColumn("Body")>
Public Class Message
Public Property MessageId As Integer ' メッセージID(主キー)
Public Property Body As String ' メッセージ本体
End Class
|
|
リスト2 メンバに対するメッセージ情報を表すMessageエンティティ(上:Message.cs、下:Message.vb) |
using System.Data.Entity;
namespace MvcTemplate.Models
{
public class MyMvcContext : DbContext
{
public DbSet<Member> Members { get; set; }
public DbSet<Message> Messages { get; set; }
}
}
|
Imports System.Data.Entity
Public Class MyMvcContext : Inherits DbContext
Public Property Members As DbSet(Of Member)
Public Property Messages As DbSet(Of Message)
End Class
|
|
リスト3 Member、Messageエンティティを管理するコンテキスト・クラス(上:MyMvcContext.cs、下:MyMvcContext.vb) |
冒頭で述べたように、DisplayFor/EditorForヘルパーは、エンティティ(プロパティ)のデータ型、メタ情報によって出力を変化させる。従って、エンティティ定義に際しても適切なメタ情報(属性)を定義しておくことは重要だ。以下に、DisplayFor/EditorForメソッドに関係する主な属性をまとめておく。
属性 |
概要 |
DataType(type) |
追加的な型情報(引数typeはMultilineText、EmailAddress、Url、Passwordなど) |
DisplayFormat(props) |
データ・フィールドを表示するための書式を指定
プロパティ |
概要 |
ApplyFormatInEditMode |
編集モード時に書式文字列を適用するか |
ConvertEmptyStringToNull |
空文字列をNothing/nullに自動変換するか |
DataFormatString |
書式文字列 |
NullDisplayText |
値がNothing/nullのときの表示テキスト |
|
指定可能な書式 |
|
|
UIHint(view) |
プロパティ値の表示/編集に使用するビューを指定 |
DisplayColumn(column) |
外部キーで関連付けられた参照先テーブルの列を指定 |
|
表1 DisplayFor/EditorForヘルパーに関係する主な属性 |
|
例えば、MemberエンティティのPasswordプロパティであれば、DataType属性によってPasswordが設定されているので、EditorForメソッドはパスワード入力ボックス(=「<input type="password" />」というコード)を出力する。
具体的に、それぞれの型、メタ情報によって、どのような出力が生成されるかについては、以下の表も参考にしていただきたい。
コントロール |
型/メタ情報 |
生成される出力 |
DisplayFor |
bool型 |
チェック・ボックス(Nullable型の場合は選択ボックス) |
ICollection型 |
参照先テーブルの列(表示列はDisplayColumn属性で指定)を列挙 |
DataType(EmailAddress) |
メール・リンク(<a href="mailto:〜">email</a>) |
DataType(Url) |
ハイパーリンク(<a href="URL">URL</a>) |
EditorFor |
bool型 |
チェック・ボックス(Nullable型の場合は選択ボックス) |
DataType(Password) |
パスワード入力ボックス |
DataType(MultilineText) |
テキストエリア |
UIHint(HiddenInput) |
隠しフィールド |
|
表2 データ型/メタ情報によるDisplayFor/EditorForヘルパーの出力 |
|
このようなMember/Messageエンティティを基にScaffold(スキャフォールド)したアプリケーションのビュー(Details.cshtmlのみ抜粋)と、その実行画面が以下だ。ただし、ICollection型のMessagesプロパティはスキャフォールディング機能では自動的に組み込まれないので、手動で追加している。
なお、データは適宜、イニシャライザ機能を使って、もしくは、Visual Studioのデータ・シートから手動で追加しておくこと。
@model MvcTemplate.Models.Member
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<fieldset>
<legend>Member</legend>
<div class="display-label">Name</div>
<div class="display-field">
@Html.DisplayFor(model => model.Name)
</div>
……中略……
<div class="display-label">Messages</div>
<div class="display-field">
@Html.DisplayFor(model => model.Messages)
</div>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.MemberId }) |
@Html.ActionLink("Back to List", "Index")
</p>
|
@ModelType MvcTemplate.Member
@Code
ViewData("Title") = "Details"
End Code
<h2>Details</h2>
<fieldset>
<legend>Member</legend>
<div class="display-label">Name</div>
<div class="display-field">
@Html.DisplayFor(Function(model) model.Name)
</div>
……中略……
<div class="display-label">Messages</div>
<div class="display-field">
@Html.DisplayFor(Function(model) model.Messages)
</div>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", New With {.id = Model.MemberId}) |
@Html.ActionLink("Back to List", "Index")
</p>
|
|
リスト4 スキャフォールディング機能で自動生成された詳細画面のビュー・テンプレート(上:Details.cshtml、下:Details.vbhtml) |
MembersControllerと、付随するビュー・テンプレートをScaffolding機能で自動生成。Messagesプロパティ(太字部分)のみ手動で書き足している。 |
|
図1 データの編集(上)/詳細画面(下) |
|
なるほど、Email/Urlなどのプロパティ値がハイパーリンクとして表示されていること、Birthプロパティが指定された書式で整形されていること、そして、Password/Infoプロパティの入力要素がそれぞれパスワード入力ボックスや複数行のテキストエリアとして出力されていることが、それぞれ確認できるはずだ。また、ICollection型のMessagesプロパティは、MessageエンティティでDisplayColumn属性として定義されたBodyプロパティの値が列挙されている点にも注目してほしい。
Insider.NET 記事ランキング
本日
月間