更新: 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 屬性。
若要將欄位範本屬性與資料欄位建立關聯
開啟想要在其中自訂資料欄位的 ASP.NET 網站。
注意事項:網站必須設定為可以使用動態資料。
在 [方案總管] 中,以滑鼠右鍵按一下 [App_Code] 資料夾,然後按一下 [加入新項目]。
在 [已安裝的範本],按一下 [類別]。
在 [名稱] 方塊中,輸入檔案的名稱。
所建立之類別的名稱必須符合代表資料表的實體類別名稱。例如,如果您要用 Customer 資料表,請將類別命名為 Customer。
在 Visual Basic 中將 Partial 關鍵字加入類別定義,或在 Visual C# 中將 partial 關鍵字加入類別定義,使其成為部分類別。
使用 Visual Basic 中的 Imports 關鍵字或 Visual C# 中的 using 關鍵字,加入對 System.ComponentModel 與 System.ComponentModel.DataAnnotations 命名空間的參考,如下範例所示:
using System.ComponentModel; using System.ComponentModel.DataAnnotations;Imports System.ComponentModel Imports System.ComponentModel.DataAnnotations在想要提供屬性 (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建立要當做部分類別之中繼資料類別的另一個類別。命名類別時,只要是目前尚未使用的名稱,您都可以使用。例如,您可以建立名稱為 CustomerMetaData 的類別,做為 Customer 類別的關聯中繼資料類別。
將 MetadataTypeAttribute 屬性加入至部分類別定義。命名屬性參數時,使用您於前一步驟所建立之關聯中繼資料類別的名稱。
[MetadataType(typeof(CustomerMetaData))] public partial class Customer { }<MetadataType(GetType(CustomerMetaData))> _ Partial Public Class Customer End Class在中繼資料類別中,將 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為了確保部分類別、中繼資料類別與屬性能夠順利運作,請執行應用程式並顯示資料表。
若要修改欄位範本以自訂的資料屬性
開啟想要自訂的欄位範本。如果您想要自訂內建的範本,請開啟對應於資料型別 (動態資料會將資料對應到的目的) 的欄位範本。
例如,如果要自訂用於顯示字串的欄位範本,則開啟 DynamicData\FieldTemplates 目錄中的 Text.ascx。
若要必要,請變更標記。
在程式碼後置檔案中,覆寫 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 Classusing 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。
請參閱
工作
變更記錄
日期 |
記錄 |
原因 |
|---|---|---|
|
2008 年 7 月 |
加入主題。 |
SP1 功能變更。 |