更新: 2008 年 7 月
在处理 ASP.NET 动态数据时,可以使用 System.ComponentModel.DataAnnotations.DataTypeAttribute 属性为数据模型字段指派一个数据类型。如果指派一个特定于该数据字段的类型,而不是由动态数据推断的 CLR 类型,将会很有用。
例如,可以将一个包含电子邮件地址的文本字段标记为电子邮件类型,该类型将被定义为文本的特定类型。处理字段的文本字段模板可以使用该属性提供的信息来创建特殊 UI,以显示和编辑电子邮件类型。使用 EmailAddress() 属性标记的文本字段可能显示为一个 System.Web.UI.WebControls.HyperLink 控件。
还可以与 UIHint 属性一起使用一个自定义字段模板,为特定的数据类型指定专用处理。使用 DataTypeAttribute 属性可以将一个字段模板用于多个类型。
决定是使用 DataTypeAttribute 属性还是使用 UIHint 属性通常是出于习惯或为了方便。有关如何使用 UIHint 属性的信息,请参见如何:自定义 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
为要为其提供属性的每个数据字段都添加一个属性访问器。
下面的示例演示如何为与 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 属性进行标记的,其值设置为 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
为确保分部类、元数据类和属性正常运行,请运行应用程序并显示表。
修改字段模板以使用自定义的数据属性
打开要自定义的字段模板。如果要自定义一个内置模板,请打开与动态数据映射数据的目标数据类型相对应的字段模板。
例如,如果要自定义用来显示字符串的字段模板,则在 DynamicData\FieldTemplates 目录中打开 Text.ascx。
根据需要更改标记。
在代码隐藏文件中重写 OnDataBinding 方法,当字段模板控件获取要显示的数据时将调用该方法。在该方法中,从派生字段模板的 FieldTemplateUserControl 类的 MetadataAttributes 属性 (Property) 中,获取当前数据字段的属性 (Attribute)。然后根据标记字段的属性可以格式化或处理数据。
下面的示例演示的代码可以用在 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() 属性 (Property) 为“BoldRed”,代码可以确定字段是用自定义 BoldRed 属性 (Attribute) 标记的。如果这样,代码就创建 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 定义为自定义属性。
编译代码
若要编译代码示例,您需要以下各项:
Microsoft Visual Studio 2008 Service Pack 1 或 Visual Web Developer 2008 速成版 Service Pack 1。
AdventureWorksLT 示例数据库。有关如何下载和安装 SQL Server 示例数据库的信息,请参见 CodePlex 站点上的 Microsoft SQL Server Product Samples: Database(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 功能更改。 |