属性によるカスタマイズ
ここまでは、ASP.NET Dynamic Dataアプリケーションの仕組みを簡単に紹介し、いくつかの機能について見てきました。次は、アプリケーションでのデータの表示をカスタマイズする方法です。
先ほど見たGlobal.asax.csファイルでは、ScaffoldAllTablesプロパティをtrueに設定していました。このように設定すると、モデルに含まれる全テーブルがアプリケーションでの編集と削除の対象として有効になります。しかし場合によっては、処理の対象となるテーブルを細かく制御したいこともあります。その場合には属性を使用します。データモデルでは、テーブルを表すクラスはパーシャルクラスとして定義されています。従って、これらのクラスに対しては、属性の指定などの実質的な機能追加を行うことが可能です。必要なコードを記述するには、プロジェクトに新しいファイルを追加する必要があります。
このファイルを追加するには、Visual Studioのソリューションエクスプローラでプロジェクトを右クリックし、[クラスの追加]を選択するのが簡単です。クラス名の入力では、「MetadataControl」などの任意の名前を指定します。ファイルを作成できたら、次にこれを編集していきます。
ここでは例として、Employeesテーブルを非表示にしたいとします。この場合、Employeeクラスのパーシャルクラスの定義を追加します。もともとは、ADO.NETエンティティモデルのファイル(先ほど例示したとおりの名前ならNorthwindModel.Designer.csファイル)で定義されているクラスです。自動生成されたスケルトンのpublicクラス定義を置き換える形で、次のコードを記述します。
[ScaffoldTable(false)]
public partial class Employees
{
}
この定義では、元のエンティティモデルで定義したEmployeesクラスを拡張し、ScaffoldTable属性を追加しています。この属性は、ASP.NET Dynamic Dataで鍵を握る属性の1つです。重要な属性の多くはSystem.ComponentModel.DataAnnotations名前空間で定義されています。この他によく使う属性としては、ScaffoldColumn(後で例を紹介)、DisplayName、DisplayFormat、Range、UIHintがあります。
上記のとおり、ScaffoldTable属性に値falseを指定したうえで、アプリケーションを実行して動作を確認してみましょう。データモデルに含まれるテーブル名を一覧表示する最初の画面では、Employeesテーブルのリンクがなくなっているはずです。また、例えばOrdersテーブルを見てみても、Employeesテーブルへのリンクがなくなっています。
テーブルの表示/非表示を制御する方法は2つあります。1つは、Global.asax.csファイルのScaffoldAllTablesプロパティですべてのテーブルを表示するよう設定したうえで、属性を使って個別のテーブルを非表示にするという方法です。もう1つはその逆で、ScaffoldAllTablesプロパティはfalseのままとしたうえで、ScaffoldTable属性(true)を使って個別のテーブルを表示させる方法です。
次は、属性を使って個別のフィールドを制御する方法です。先ほどは、パーシャルクラスを使ってScaffoldTable属性を指定するというやり方でしたが、個々の列に属性を関連付けたい場合には、別の策が必要です。パーシャルプロパティの定義はできないので、別のクラスを追加して、データベースフィールドに対応するプロパティを定義する必要があります。
それにはまず、先ほどのScaffoldTable属性の場合と同様のパーシャルクラスを作成します。ただしこちらは、MetadataType属性を使って、元のクラスに別のクラスを関連付けます。この追加クラスをメタデータクラスと言います。次にこのクラスを使って、データモデルで制御する対象となる各フィールドに対応するpublicプロパティを定義します。次のコードはその例です。
[MetadataType(typeof(EmployeesMetadata))]
public partial class Employees
{
}
class EmployeesMetadata
{
[DisplayName("Person's title")]
public object Title { get; set; }
}
ここでは、先ほどと同様にパーシャルクラスEmployeesを定義していますが、MetadataType属性をあわせて適用しています。この属性のコンストラクタはパラメータとして型を受け取ります。ここではEmployeesMetadataというメタデータクラスを指定しています。このクラスを使うことで、新しいプロパティや関連するフィールドレベルの属性を自由に定義できます。例えばこの例では、Title列にDisplayName属性(System.ComponentModel名前空間で定義)を関連付けて、フィールドの内容を分かりやすく伝える新しいタイトルを指定しています。もちろん、プロパティ名がデータベースのものと一致していないと正常に機能しません。
ユーザーインターフェースのカスタマイズ
ASP.NET Dynamic Dataアプリケーションでは、属性の使い方を理解することが成否の鍵を握りますが、属性と共にアプリケーションのユーザーインターフェースを形成するWebページのテンプレートについても、そのカスタマイズ方法を知っておく必要があります。先ほど簡単に触れたように、ASP.NET Dynamic DataアプリケーションはデフォルトでASP.NETテンプレートファイルを使用します。ファイル名はSite.masterで、プロジェクトのルートフォルダにあります。
ユーザーインターフェースを変更する場合、Site.masterファイルの編集から手を付けるのが適切です。このファイルでは、XHTMLコードを使用してコンテンツのプレースホルダを1つ定義します。このプレースホルダに、実際のページ内容が実行時に埋め込まれます。このファイルではCSSのスタイルもあわせて指定します。スタイルの定義はSite.cssで行います。アプリケーション全体のフォントや色を変更する場合には、このCSSファイルを編集するのがよいでしょう。
テンプレートとスタイルシートのファイルに加え、4つの基本操作を実装した.aspxページ自体ももちろん使用します。これらのファイルはソリューションのDynamicData\PageTemplatesフォルダにあります。例えば、一覧ページの動作を変更する場合なら、List.aspxを編集します。
カスタマイズでもう1つ関係してくるのが、DynamicData\FieldTemplatesフォルダのファイルです。このフォルダには、データベースの各種フィールドを表示するためにASP.NET Dynamic Dataが使用するユーザーコントロールがあります。例えば、Boolean型のフィールドは画面上ではチェックボックスとして表示されます。この動作を変えるには、Boolean.ascxファイルとBoolean_Edit.ascxファイルを編集します。通常、各データ型に対応するコントロールは2つずつ定義されています。1つは表示用、もう1つは編集用です。多くの場合、表示コントロールは編集コントロールの読み取り専用バージョンとなっています。
また、データに対して使用するユーザーコントロールを独自に定義することも可能です。例えば、日付の表示に使用するコントロールを変えたいとしましょう。デフォルトでは、DateTime.ascxファイルはテキストボックスコントロールを使用しますが、これをカレンダーコントロールなどに変更するのは簡単です。アプリケーション全体で変更したい場合なら、DateTime.ascxを編集するだけで、すべての日付フィールドに変更が反映されます。また、フィールド単位で変更することも可能です。その場合は、前出のScaffoldTable属性やScaffoldColumn属性と同じように属性を使います。例えば、カレンダーのユーザーコントロールをDataTimeCalendar.ascxで次のように実装したとしましょう。
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DateTimeCalendar.ascx.cs" Inherits="DynamicDataTest.DynamicData. FieldTemplates.DateTimeCalendar" %> <asp:Calendar ID="Calendar1" runat="server"> </asp:Calendar>
この宣言は通常のユーザーコントロールの定義と同様ですが、ASP.NET Dynamic Dataでの使用に適合させるために、コードビハインドファイルに若干の違いがあります。まず、継承チェーンを通常のSystem.Web.UI.UserControlからSystem.Web.DynamicData.FieldTemplateUserControlに変更する必要があります。
もちろん、使用できるコントロールはASP.NETに備わっているものだけではありません。例えば、多機能で見栄えのいいサードパーティ製コントロールを購入した場合や、自作のコントロールがある場合は、ASP.NET Dynamic Dataアプリケーションでも使用できます。データの表示に使用するユーザーコントロールはUIHint属性で指定できます。ScaffoldColumn属性と同様にメタデータクラスに適用する属性です。DateTimeCalendarユーザーコントロールを前述のように宣言したうえで、UIHint属性を次のように使用します。
[MetadataType(typeof(EmployeesMetadata))]
public partial class Employees
{
}
class EmployeesMetadata
{
...
[UIHint("DateTimeCalendar")]
public object HireDate { get; set; }
}
このコードでは、EmployeesテーブルのHireDateフィールドに対し、UIHint属性として"DateTimeCalendar"という値を指定しています。テーブルの表示では、標準のテキストラベルの代わりにカレンダーコントロールが使用されます(図7を参照)。なお、カレンダーで正しい入社日を表示できるよう、ユーザーコントロールのコードビハインドファイルに次のような数行のコードを記述する必要があります。
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
object val = FieldValue;
if (val != null)
{
Calendar1.SelectedDate = (DateTime)val;
Calendar1.VisibleDate = Calendar1.SelectedDate;
}
}
こうしたコードを除けば、カスタムコントロールを使ったページのカスタマイズは非常に簡単です。この例からも分かるように、一覧表示や編集ページでは、ラベルやテキストボックスばかりを使用する必要はありません。

