共用方式為


HOW TO:自訂資料模型中非內建資料型別的資料欄位外觀和行為

更新: 2008 年 7 月

當您使用 ASP.NET Dynamic Data 時,您可以利用 System.ComponentModel.DataAnnotations.DataTypeAttribute 屬性指派資料型別給資料模型欄位。如果您要指派更專屬於該資料欄位的型別,而不要使用動態資料所推測出的 CLR 型別,這個方法則相當實用。

例如,您可以將包含電子郵件地址的文字欄位,標記為以定義為特定文字型別的電子郵件型別。處理欄位的文字欄本範本可以使用這個屬性提供的資訊,建立供顯示與編輯電子郵件型別的特殊 UI。以 EmailAddress() 屬性標記的文字欄位可能會顯示為 System.Web.UI.WebControls.HyperLink 控制項。

您也可以將 UIHint 屬性與自訂欄本範本一併使用,指定特定資料型別的特殊處理方式。DataTypeAttribute 屬性可以讓您將一種欄位範本用於多種型別。

決定要使用 DataTypeAttribute 屬性還是 UIHint 屬性,通常是考量樣式與方便性的問題。如需如何使用 UIHint 屬性的詳細資訊,請參閱 HOW TO:自訂 ASP.NET 動態資料預設欄位範本

本主題說明如何使用 DataTypeAttribute 屬性。

若要將欄位範本屬性與資料欄位建立關聯

  1. 開啟想要在其中自訂資料欄位的 ASP.NET 網站。

    注意事項:

    網站必須設定為可以使用動態資料。

  2. 在 [方案總管] 中,以滑鼠右鍵按一下 [App_Code] 資料夾,然後按一下 [加入新項目]。

  3. 在 [已安裝的範本],按一下 [類別]。

  4. 在 [名稱] 方塊中,輸入檔案的名稱。

    所建立之類別的名稱必須符合代表資料表的實體類別名稱。例如,如果您要用 Customer 資料表,請將類別命名為 Customer。

  5. 在 Visual Basic 中將 Partial 關鍵字加入類別定義,或在 Visual C# 中將 partial 關鍵字加入類別定義,使其成為部分類別。

  6. 使用 Visual Basic 中的 Imports 關鍵字或 Visual C# 中的 using 關鍵字,加入對 System.ComponentModelSystem.ComponentModel.DataAnnotations 命名空間的參考,如下範例所示:

    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    
    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations 
    
  7. 在想要提供屬性 (Attribute) 的每一個資料欄位中,加入屬性 (Property) 存取子。

    下列範例說明如何建立三個屬性 (對應於 Customer 資料表的三個欄位) 的屬性存取子。

    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 欄位會以設為 false 的 ScaffoldColumnattribute 屬性標記。如此可以不讓欄位由動態資料顯示。ModifiedDate 欄位會以值為設為 DataType.Date 的 DataType 屬性標記。這會指定該欄位的資料要以簡短日期格式顯示。

    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 屬性進行標記。如果是,程式碼會建立 UI,以顯示樣式為紅色文字之 Label 控制項中的資料。

範例

在下列範例中,會示範如何自訂非內建資料型別的資料欄位外觀和行為。程式碼自訂動態資料會如何顯示 AdventureWorksLT 資料庫中 Customer 資料表的 EmailAddress、SalesPerson 與 LastName 欄位。

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; }
} 

範例中,DataTypeAttribute 屬性 (Attribute) 會設為 EmailAddress 屬性 (Property) 的 EmailAddress()。DataTypeAttribute 屬性 (Attribute) 會設為 SalesPerson 屬性 (Property) 的 Url(),DataTypeAttribute 屬性 (Attribute) 會設為 LastName 屬性 (Property) 的 BoldRed。BoldRed 則定義為自訂屬性 (Property)。

編譯程式碼

若要編譯這段範例程式碼,您需要下列項目:

  • Microsoft Visual Studio 2008 Service Pack 1 或 Visual Web Developer 2008 Express 版 Service Pack 1。 

  • AdventureWorksLT 範例資料庫。如需下載並安裝 SQL Server 範例資料庫,請參閱 CodePlex 網站上的 Microsoft SQL Server 產品範例:資料庫 (英文)。請確認已配合您所執行的 SQL Server 版本 (Microsoft SQL Server 2005 或 Microsoft SQL Server 2008) 安裝版本正確的範例資料庫。

  • 動態資料驅動的網站。這可以讓您建立資料庫的資料內容,並且建立包含可以自訂之資料欄位的類別與要覆寫的方法。如需詳細資訊,請參閱Walkthrough: Creating a New Dynamic Data Web Site using Scaffolding

請參閱

工作

HOW TO:自訂 ASP.NET 動態資料預設欄位範本

變更記錄

日期

記錄

原因

2008 年 7 月

加入主題。

SP1 功能變更。