生成コードのカスタマイズ
最後に、Scaffoldingで生成されたコードのカスタマイズ方法を簡単に紹介します。今回行うカスタマイズは次のとおりです。
- 会議室メンテナンス画面を作成する
- 会議室情報を入力する際、場所をドロップダウンリストで選択する
- UIを日本語化する
ポイントは、ASP.NET Dynamic Dataの「フィールドテンプレート」を使うことです。今回のカスタマイズに当たり、以下の記事を参考にしましたので、併せて確認してください。
それでは、順番に見ていきましょう。
会議室メンテナンス画面を作成する
カスタマイズを行う元コードを生成するため、会議室のデータモデルクラス「MeetingRoom」を新たに作成し、Scaffoldingでコードを生成します(リスト4)。
using System; using System.ComponentModel.DataAnnotations; namespace MRRS_Scaffolding.Models { public class MeetingRoom { [ScaffoldColumn(false)] public int Id { get; set; } [Display(Name = "会議室名")] [Required(ErrorMessage = "会議室名を入力してください。")] public string Name { get; set; } [Display(Name = "場所")] [UIHint("Location")] [Required(ErrorMessage = "場所を入力してください。")] public int LocationId { get; set; } } }
ここでのポイントは、会議室データモデル内の場所ID(LocationId)にUIHint属性を指定していることです。UIHint属性を指定することで、Dynamic Dataが使用するテンプレートファイルを明示的に指定できます。ここでは"Location"という名前を指定します。
場所をドロップダウンリストで選択
DynamicData\FieldTemplatesフォルダーに、表示、編集用にDynamic Dataのフィールドテンプレートファイルを、それぞれLocation.ascx(.cs)、Location_Edit.ascx(.cs)として作成します(Enumeration.ascx、Enumeration_Edit.ascxをコピーして直すと簡単です)。これらのファイル名の"Location"はデータモデルのフィールドにUIHint属性で指定した名前と同じにします。このようにするのは、Dynamic Dataのテンプレート選択順がUIHint→フィールドの型の順になっているためです。従って、MeetingRoomクラスのLocationIdフィールドにUIHint属性を設定しないと、DynamicData\FieldTemplatesフォルダーのInteger.ascx(.cs)とInteger_Edit.ascx(.cs)がテンプレートとして使われます。
では、実際のコードを見てみましょう。まずは場所を表示するLocation.ascx(.cs)からです(リスト5、6)。
<%@ Control Language="C#" CodeBehind="Location.ascx.cs" Inherits="MRRS_Scaffolding.LocationField" AutoEventWireup="True" %> <%-- コードビハインドに定義したGetNameメソッドで場所名を取得表示する --%> <asp:Literal runat="server" ID="Literal1" Text="<%# GetName() %>" />
using System using System.Web.UI; using MRRS_Scaffolding.Models; namespace MRRS_Scaffolding { public partial class LocationField : System.Web.DynamicData.FieldTemplateUserControl { public string GetName() { // データバインドしたフィールドの値を取得 // (結果としてLocationIdが取得できる) var id = (int)FieldValue; // LocationIdに対応する場所名を取得、返却する var context = new MRRSContext(); var record = context.Location.Find(id); return record.Name; } } }
まず、ascxファイル側で場所を表示する際、コードビハインドに定義したGetNameメソッドを使ってその内容を取得するようにします。GetNameメソッドでは、生成したMRRSContextクラスを使い、Idに対応した場所名を取得、返却します。このときはIdはデータバインドされた値を使うため、FieldValueプロパティから取得します。
次に登録画面、編集画面で使用される、場所の入力を行うLocation_Edit.ascx(.cs)です(リスト7、8)。
<%@ Control Language="C#" CodeBehind="Location_Edit.ascx.cs" Inherits="MRRS_Scaffolding.Location_EditField" AutoEventWireup="True" %> <%-- 場所を表示するドロップダウンリスト --%> <asp:DropDownList ID="DropDownList1" runat="server" CssClass="DDDropDown" DataSourceID="LinqDataSource1" DataTextField="Name" DataValueField="Id" AppendDataBoundItems="true"> <asp:ListItem Text="" Value="" /> </asp:DropDownList> <%-- MRRSContextクラスを使い、場所のId、名前をドロップダウンリスト編集用に取得する --%> <asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="MRRS_Scaffolding.Models.MRRSContext" EntityTypeName="" Select="new (Id, Name)" TableName="Location"></asp:LinqDataSource> <%-- 場所は必須入力とする --%> <asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1" CssClass="DDControl DDValidator" ControlToValidate="DropDownList1" Display="Static" Enabled="false" /> <%-- その他、動的な入力チェックに対応する --%> <asp:DynamicValidator runat="server" ID="DynamicValidator1" CssClass="DDControl DDValidator" ControlToValidate="DropDownList1" Display="Static" />
using System; using System.Collections.Specialized; using System.Web.UI; namespace MRRS_Scaffolding { public partial class Location_EditField : System.Web.DynamicData.FieldTemplateUserControl { protected void Page_Load(object sender, EventArgs e) { // 検証コントロールをValidationGroupに所属させる SetUpValidator(RequiredFieldValidator1); SetUpValidator(DynamicValidator1); } protected override void OnDataBinding(EventArgs e) { base.OnDataBinding(e); // データを表示するタイミングで、場所Idに対応するリスト項目を表示させる DropDownList1.SelectedValue = FieldValueString; } protected override void ExtractValues(IOrderedDictionary dictionary) { // 入力したデータをデータソースに反映させるタイミングで、 // 選択した場所のIdを設定する dictionary[Column.Name] = DropDownList1.SelectedValue; } } }
場所をドロップダウンリストで入力させるため、DropDownListコントロールを配置します。そして、DataSourceIdに表示する場所を取得するためのデータソースコントロールを指定します。今回はLinqDataSourceコントロールを使い、MRRSContextを使って場所を取得しています。
コードビハインド側では、まずPage_Loadでascxファイルで追加した検証コントロールを、ValidationGroupに所属させるため、SetUpValidatorメソッドを呼び出します。
次に、データバインドしたデータを表示する際、Idに対応して選択項目を表示するため、OnDataBindingメソッドをオーバーライドします。表示側と違い、ここではId値を文字列として使用したいので、FieldValueStringプロパティを使います。
最後に、選択した場所の値をデータソース側にバインドするため、ExtractValuesメソッドをオーバーライドします。このメソッドでは、dictionay引数にデータソースの項目名をキーとして値を設定することで、データソースにその値を設定できます。従って、DropDownListのSelectedValueプロパティで、選択した場所のIdを設定します。