方法 : データ モデルの非組み込みデータ型に合わせてデータ フィールドの外観と動作をカスタマイズする

更新 : 2008 年 7 月

ASP.NET Dynamic Data では、System.ComponentModel.DataAnnotations.DataTypeAttribute 属性を使用して、特定のデータ型を特定のデータ モデル フィールドに割り当てることができます。この方法は、Dynamic Data によって推論される CLR 型ではなく、より具体的にデータ フィールドの型を割り当てる必要がある場合などに役立ちます。

たとえば、電子メール アドレスを含んだテキスト フィールドを、特殊な種類のテキストとして定義された電子メール型として指定できます。このフィールドを処理するテキスト フィールド テンプレートは、この属性によって指定された情報を使用して、電子メール型の表示と編集に特化した UI を作成します。EmailAddress() 属性でマークされたテキスト フィールドを、System.Web.UI.WebControls.HyperLink コントロールとして表示させることも可能です。

特定のデータ型に対して特殊な処理を指定する方法としては、カスタム フィールド テンプレートと UIHint を組み合わせて使用する方法もあります。DataTypeAttribute 属性では、複数の型に対して 1 つのフィールド テンプレートを使用できます。

通常、DataTypeAttribute 属性と UIHint 属性は、使いやすい方を任意に選んで使用できます。UIHint プロパティの使用方法については、「方法 : ASP.NET Dynamic Data の既定のフィールド テンプレートをカスタマイズする」を参照してください。

このトピックでは、DataTypeAttribute 属性の使用方法を説明します。

DataTypeAttribute とデータ フィールドとを関連付けるには

  1. カスタマイズするデータ フィールドがある ASP.NET Web サイトを開きます。

    Cc668199.alert_note(ja-jp,VS.90).gifメモ :

    Dynamic Data に必要な Web サイト構成が済んでいる必要があります。

  2. ソリューション エクスプローラで、App_Code フォルダを右クリックし、[新しい項目の追加] をクリックします。

  3. [インストールされているテンプレート][クラス] をクリックします。

  4. [名前] ボックスにファイルの名前を入力します。

    作成するクラスの名前は、テーブルを表すエンティティ クラス名と一致させる必要があります。たとえば、Customer テーブルを使用する場合は、「Customer」というクラス名にします。

  5. クラス定義に Partial キーワード (Visual Basic の場合) または partial キーワード (Visual C# の場合) を追加して部分クラスにします。

  6. Imports キーワード (Visual Basic の場合) または using キーワード (Visual C# の場合) を使用して、System.ComponentModel 名前空間と System.ComponentModel.DataAnnotations 名前空間への参照を追加します。次に例を示します。

    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    
    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations 
    
  7. 属性を適用する各データ フィールドのプロパティ アクセサを追加します。

    Customer テーブルのフィールドに対応する 3 つのプロパティのプロパティ アクセサを作成する方法の例を次に示します。

    public class CustomerMetaData {
    
        public object PasswordHash { get; set; }
        public object PasswordSalt { get; set; }
        public object ModifiedDate { get; set; }    
    }
    
    Public Class CustomerMetaData
    
        Public PasswordHash As Object
        Public PasswordSalt As Object
        Public ModifiedDate As Object
    End Class
    
  8. 部分クラスの関連メタデータ クラスとして機能する別のクラスを作成します。このクラスには、まだ使用されていない任意の名前を付けることができます。たとえば、CustomerMetaData という名前のクラスを、Customer クラスの関連メタデータ クラスとして作成できます。

  9. 部分クラス定義に MetadataTypeAttribute 属性を追加します。属性のパラメータには、前の手順で作成した関連メタデータ クラスの名前を使用します。

    [MetadataType(typeof(CustomerMetaData))]
    public partial class Customer {
    
    }
    
    <MetadataType(GetType(CustomerMetaData))> _
    Partial Public Class Customer
    
    End Class
    
  10. メタデータ クラスで、表示または動作の変更対象となる各フィールドに DataAnnotations 属性を追加します。

    次の例は、完成した Customer テーブルの部分クラスと、CustomerMetaData という名前の関連メタデータ クラスを示しています。メタデータ クラスには、データベースのフィールドに対応するパブリック クラス フィールドが存在します。PasswordHash フィールドおよび PasswordSalt フィールドに指定された ScaffoldColumnattribute 属性は、false に設定されています。これにより、フィールドが Dynamic Data によって表示されるのを防いでいます。ModifiedDate フィールドには DataType 属性が指定され、その値が DataType.Date に設定されています。このように指定することで、このフィールドのデータが短い日付形式で表示されます。

    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    
    [MetadataType(typeof(CustomerMetaData))]
    public partial class Customer { }
    
    public class CustomerMetaData {
    
       [ScaffoldColumn(false)]
        public object PasswordHash { get; set; }
    
        [ScaffoldColumn(false)]
        public object PasswordSalt { get; set; }
    
        [DataTypeAttribute(DataType.Date)]
        public object ModifiedDate { get; set; }   
    
    }
    
    Imports Microsoft.VisualBasic
    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations
    
    <MetadataType(GetType(CustomerMetaData))> _
    Partial Public Class Customer
    
    End Class
    
    Public Class CustomerMetaData
    
            <ScaffoldColumn(False)> _
        Public PasswordSalt As Object
    
        <DataTypeAttribute(DataType.Date)> _
    Public PasswordSalt As Object
    
        <DataTypeAttribute(DataType.Date)> _
    Public ModifiedDate As Object  
    End Class
    
  11. 部分クラス、メタデータ クラス、および属性が正常に機能することを確認するために、アプリケーションを実行してテーブルを表示します。

フィールド テンプレートを変更してカスタマイズされたデータ属性を使用するには

  1. カスタマイズするフィールド テンプレートを開きます。組み込みのテンプレートをカスタマイズする場合は、データ型に対応するフィールド テンプレートを開きます。

    たとえば、文字列表示用のフィールド テンプレートをカスタマイズする場合は、DynamicData\FieldTemplates ディレクトリの Text.ascx を開きます。

  2. 必要に応じて、マークアップを変更します。

  3. 分離コード ファイルで、OnDataBinding メソッドをオーバーライドします。このメソッドは、フィールド テンプレート コントロールが表示するデータを取得したタイミングで呼び出されます。このメソッドで、フィールド テンプレートの派生元の FieldTemplateUserControl クラスの MetadataAttributes プロパティから、現在のデータ フィールドの属性を取得します。これで、フィールドに指定された属性に応じて、データの書式を設定したり、データを加工したりできます。

    たとえば、このトピックの前半で変更したデータ フィールドであれば、Text.ascx フィールド テンプレートに次のコードを使用することによって表示できます。

    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Collections
    Imports System.Collections.Specialized
    Imports System.Linq
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    Imports System.Xml.Linq
    Imports System.Web.DynamicData
    Imports System.ComponentModel.DataAnnotations
    
    Partial Class TextField
        Inherits System.Web.DynamicData.FieldTemplateUserControl
    
        Private Function getNavUrl() As String
            Dim metadata = MetadataAttributes.OfType(Of DataTypeAttribute).FirstOrDefault()
            If (metadata Is Nothing) Then
                Return FieldValueString
            End If
    
            Dim url As String = FieldValueString
    
            Select Case metadata.DataType
    
                Case DataType.Url
                    url = FieldValueString
                    If (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) Or _
                       url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) Then
                        Return url
                    End If
    
                    Return "http://" + FieldValueString
    
                Case DataType.EmailAddress
                    Return "mailto:" + FieldValueString
    
                Case Else
                    Throw New Exception("Unknow DataType")
    
            End Select
    
        End Function
    
    
        Protected Overrides Sub OnDataBinding(ByVal e As System.EventArgs)
            MyBase.OnDataBinding(e)
    
            If (String.IsNullOrEmpty(FieldValueString)) Then
                Return
            End If
    
            Dim metadata = MetadataAttributes.OfType(Of DataTypeAttribute).FirstOrDefault()
    
            If (metadata Is Nothing Or String.IsNullOrEmpty(FieldValueString)) Then
                Dim literal As New Literal()
                literal.Text = FieldValueString
                Controls.Add(literal)
                Return
            End If
    
            If (metadata.DataType = DataType.Url Or _
                metadata.DataType = DataType.EmailAddress) Then
    
                Dim hyperlink As New HyperLink
                hyperlink.Text = FieldValueString
                hyperlink.href = getNavUrl()
                hyperlink.Target = "_blank"
                Controls.Add(hyperlink)
                Return
    
            End If
    
            If (metadata.DataType = DataType.Custom And _
                 String.Compare(metadata.CustomDataType, "BoldRed", True) = 0) Then
                Dim lbl As New Label()
                lbl.Text = FieldValueString
                lbl.Font.Bold = True
                lbl.ForeColor = System.Drawing.Color.Red
                Controls.Add(lbl)
            End If
    
        End Sub
    
    End Class
    
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Xml.Linq;
    using System.Web.DynamicData;
    using System.ComponentModel.DataAnnotations;
    
    public partial class TextField : System.Web.DynamicData.FieldTemplateUserControl {
    
        string getNavUrl() {
    
            var metadata = MetadataAttributes.OfType<DataTypeAttribute>().FirstOrDefault();
            if (metadata == null)
                return FieldValueString; 
    
            switch (metadata.DataType) {
    
                case DataType.Url:
                    string url = FieldValueString;
                    if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                        url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
                        return url;
    
                    return "http://" + FieldValueString;
    
    
                case DataType.EmailAddress:
                    return "mailto:" + FieldValueString;
    
                default:
                    throw new Exception("Unknown DataType");
            }
        }
    
        protected override void OnDataBinding(EventArgs e) {
            base.OnDataBinding(e);
    
            if (string.IsNullOrEmpty(FieldValueString))
                return;
    
            var metadata = MetadataAttributes.OfType<DataTypeAttribute>().FirstOrDefault();
    
            if (metadata == null || string.IsNullOrEmpty(FieldValueString)) {
                Literal literal = new Literal();
                literal.Text = FieldValueString;
                Controls.Add(literal);
                return;
            }
    
            if (metadata.DataType == DataType.Url ||
                metadata.DataType == DataType.EmailAddress) {
    
                HyperLink hyperlink = new HyperLink();
                hyperlink.Text = FieldValueString;
                hyperlink.href = getNavUrl();
                hyperlink.Target = "_blank";
                Controls.Add(hyperlink);
                return;
            }
    
            if (metadata.DataType == DataType.Custom &&
               string.Compare(metadata.CustomDataType, "BoldRed", true) == 0) {
                Label lbl = new Label();
                lbl.Text = FieldValueString;
                lbl.Font.Bold = true;
                lbl.ForeColor = System.Drawing.Color.Red;
                Controls.Add(lbl);
            }
    
        }
    
    }
    

    このコードでは、まず、現在のフィールドの属性が取得されます。フィールドに指定された属性を調べ、その結果に応じて異なるロジックが実行されます。たとえば、Custom() の判定を行い、CustomDataType() プロパティが "BoldRed" であることが確認できれば、そのフィールドにカスタムの BoldRed 属性が指定されていると判断できます。その場合は、赤色のテキストとして設定された Label コントロールにデータを表示する UI が作成されます。

使用例

非組み込みデータ型向けに、データ フィールドの外観と動作をカスタマイズする方法を次の例に示します。このコードでは、AdventureWorksLT データベースに存在する Customer テーブルの EmailAddress、SalesPerson、および LastName の各フィールドについて、Dynamic Data による表示がカスタマイズされます。

Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations

<MetadataType(GetType(CustomerMetaData))> _
Partial Public Class Customer

End Class


Public Class CustomerMetaData

    <ScaffoldColumn(False)> _
    Public PasswordHash As Object

    <ScaffoldColumn(False)> _
    Public PasswordSalt As Object

    <DataTypeAttribute(DataType.Date)> _
    Public ModifiedDate As Object

    <DataTypeAttribute(DataType.EmailAddress)> _
    Public EmailAddress As Object

    <DataTypeAttribute(DataType.Url)> _
    Public SalesPerson As Object


    <DataTypeAttribute("BoldRed")> _
    <DisplayName("Last")> _
    Public ReadOnly Property LastName() As Object
        Get
            Return ""
        End Get
    End Property

End Class
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(CustomerMetaData))]
public partial class Customer {
}

public class CustomerMetaData {

    [ScaffoldColumn(false)]
    public object PasswordHash { get; set; }

    [ScaffoldColumn(false)]
    public object PasswordSalt { get; set; }

    [DataTypeAttribute(DataType.Date)]
    public object ModifiedDate { get; set; }

    [DataTypeAttribute(DataType.EmailAddress)]
    public object EmailAddress { get; set; }

    [DataTypeAttribute(DataType.Url)]
    public object SalesPerson { get; set; }

    [DisplayName("Last")]
    [DataTypeAttribute("BoldRed")]
    [RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$", 
        ErrorMessage = "Characters are not allowed.")]

    public object LastName { get; set; }
} 

この例では、EmailAddress プロパティの DataTypeAttribute 属性が EmailAddress() に設定されます。SalesPerson プロパティの DataTypeAttribute 属性は Url() に設定されます。また、LastName プロパティの DataTypeAttribute 属性は BoldRed に設定されます。BoldRed は、カスタム プロパティとして定義されています。

コードのコンパイル方法

このコード例をコンパイルするには、以下が必要です。

  • Microsoft Visual Studio 2008 Service Pack 1 または Visual Web Developer 2008 Express Edition Service Pack 1。

  • AdventureWorksLT サンプル データベース。SQL Server のサンプル データベースをダウンロードしてインストールする方法については、CodePlex サイトの「Microsoft SQL Server Product Samples: Database」を参照してください。実行している SQL Server のバージョン (Microsoft SQL Server 2005 または Microsoft SQL Server 2008) に対応した正しいバージョンのサンプル データベースをインストールしてください。

  • 動的なデータ ドリブン Web サイト。これにより、カスタマイズするデータ フィールドおよびオーバーライドするメソッドを持つクラスと、データベースのデータ コンテキストを作成できます。詳細については、「Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding」を参照してください。

参照

処理手順

方法 : ASP.NET Dynamic Data の既定のフィールド テンプレートをカスタマイズする

履歴の変更

日付

履歴

理由

2008 年 7 月

トピックを追加

SP1 機能変更