如何:在数据模型中自定义数据字段的外观和行为
更新:2007 年 11 月
ASP.NET 动态数据包括用于显示和编辑数据字段的 UI 的字段模板。可以通过更改现有字段模板以及通过创建新的自定义字段模板来自定义该 UI。
本主题介绍如何通过执行以下步骤来自定义数据字段的外观和行为:
将 UIHintAttribute 属性应用于数据模型中的数据字段。这会指示动态数据使用特定的自定义字段模板来处理数据字段。
创建相应的自定义字段模板来呈现用于显示和编辑数据字段的 UI。
在数据层中自定义数据字段时,如本主题中所示,自定义会全局性应用于整个网站。动态数据使用自定义字段模板代替内置模板(根据数据字段内部类型进行选择的)来显示和修改数据字段。
或者,可以将自定义限制到单个页面。有关更多信息,请参见如何:使用自定义网页模板自定义单个表的布局。
在数据层中自定义数据字段需要几个步骤。本主题中的过程介绍该过程的各个步骤。
运行此功能的在线示例。
在数据模型中指定自定义字段模板
本节介绍将自定义字段模板与数据字段相关联的步骤。
对数据字段应用属性
在**“解决方案资源管理器”中右击 App_Code 文件夹,再单击“添加新项”**。
在**“Visual Studio 已安装的模板”下方单击“类”**。
在**“名称”**框中输入包含可供自定义字段模板显示的数据的数据库表名称(在数据模型中定义)。
文件名必须是表示该表的实体类名。例如,如果自定义字段模板要显示 SalesOrderDetail 表中的数据,则将文件命名为 SalesOrderDetail.cs 或 SalesOrderDetail.vb,将类命名为 SalesOrderDetail。创建的类文件还将包含一个关联类,通过该关联类可以对数据字段应用属性。
将 Visual Basic 中的 Partial 关键字或 Visual C# 中的 partial 关键字添加到类定义中,使其成为分部类。如果使用的是 Visual C#,请删除默认构造函数。
使用 Visual Basic 中的 Imports 关键字或 Visual C# 中的 using 关键字导入 System.Web.DynamicData 和 System.ComponentModel.DataAnnotations 命名空间,如下面的示例所示:
using System.Web.DynamicData; using System.ComponentModel.DataAnnotations;
Imports System.Web.DynamicData Imports System.ComponentModel.DataAnnotations
在从步骤 1 到步骤 3 创建的类文件中,创建将充当关联元数据类的另一个分部类。对于该类,可以使用任何名称。
下面的示例演示如何为 SalesOrderDetail 字段创建关联元数据类。
public partial class SalesOrderDetailMetadata { }
Partial Public Class SalesOrderDetailMetadata End Class
将 MetadataTypeAttribute 属性添加到数据表的分部类定义中。对于该属性的参数,请指定在上一步中创建的元数据类的名称。
下面的示例演示如何应用该属性,以将 SalesOrderDetail 分部类与其关联元数据类连接起来。
[MetadataType(typeof(SalesOrderDetailMetadata))] public partial class SalesOrderDetail { }
<MetadataType(GetType(SalesOrderDetailMetadata))> _ Partial Public Class SalesOrderDetail End Class
在关联元数据类中,创建一个与要自定义的数据字段相匹配的公共属性。
将 UIHintAttribute 属性 (Attribute) 应用于该属性 (Property),从而指定用于显示和编辑的自定义字段模板的名称。
Object 类型在元数据类中用作可表示数据字段的占位符类型。动态数据在运行时从数据模型推断实际类型。
public partial class SalesOrderDetailMetadata { [UIHint("CustomFieldTemplate")] public object OrderQty; }
Partial Public Class SalesOrderDetailMetadata <UIHint("CustomFieldTemplate")> _ Public OrderQty As Object End Class
保存并关闭类文件。
创建自定义字段模板
字段模板是用户控件,动态数据使用它们来呈现用于显示和编辑数据字段的 UI。本节介绍创建自定义字段模板以呈现用于显示数据字段的 UI 的步骤。
创建用于显示的自定义字段模板
在**“解决方案资源管理器”中右击 DynamicData\FieldTemplates 文件夹,再单击“添加新项”**。
在**“Visual Studio 已安装的模板”下方单击“动态数据字段”**。
在**“名称”框中输入自定义字段模板的名称。可以使用任何尚未使用的名称。请确保已选中“将代码放在单独的文件中”**框。
单击**“添加”**。
Visual Studio 将创建两个字段模板,一个用于显示,一个用于编辑。例如,如果输入的名称为 CustomFieldTemplate.ascx,则 Visual Studio 将创建 CustomFieldTemplate.ascx 和 CustomFieldTemplate_Edit.ascx。第一个模板呈现用于显示数据字段的 UI,第二个模板呈现用于编辑数据字段的 UI。
如果要自定义数据字段的显示,请打开显示用户控件文件并添加自定义。
下面的示例演示一个用于显示数据的自定义字段模板。在本示例中,将 Literal 控件(默认在动态数据字段模板中提供)替换为 Label 控件(其 Text 属性设置为当前字段值字符串)。可以使用 FieldValueString 属性访问数据字段的值。
<asp:Label id="Label1" runat="server" Text='<%# FieldValueString %>'> </asp:Label>
如果需要自定义,请打开显示字段模板的代码隐藏文件并添加自定义。
下面的示例演示如何将代码与您对上一步中显示的标记所进行的更改相同步。在代码中,Literal1 标识符替换为 Label1 标识符,以支持用于显示的 UI 自定义。
public override Control DataControl { get {return Label1;} }
Public Overrides ReadOnly Property DataControl() As Control Get Return Label1 End Get End Property
重写字段模板的 OnDataBinding 方法,添加代码以自定义数据字段显示。
在此方法中,可以从控件的 FieldValue 属性获取当前数据字段的值,然后自定义显示,如下面的示例所示。
protected override void OnDataBinding(EventArgs e) { if (currentQty < min) { Label1.ForeColor = System.Drawing.Color.Red; Label1.Font.Bold = true; } else if (currentQty > max) { Label1.ForeColor = System.Drawing.Color.Blue; Label1.Font.Bold = true; } } }
Protected Overloads Overrides Sub OnDataBinding( _ ByVal e As EventArgs) If currentQty < min Then Label1.ForeColor = System.Drawing.Color.Red Label1.Font.Bold = True ElseIf currentQty > max Then Label1.ForeColor = System.Drawing.Color.Blue Label1.Font.Bold = True End If End If End Sub
下一过程介绍创建自定义字段模板以呈现用于编辑数据字段的 UI 的步骤。
创建用于编辑的自定义字段模板
打开其名称以 _Edit 后缀结尾的自定义字段模板并添加自定义。
下面的示例演示添加 CustomValidator 控件(常规参考)控件的标记,以在用户输入的数据无效时显示自定义警告消息。例如,如果数据字段值超出在字段模板中定义的特定限制,就会显示一条消息。本示例将验证程序的 Display 属性设置为“Dynamic”,这样仅当验证失败时才会显示验证控件。代码将 ControlToValidate 属性设置为要验证的控件的 ID。它还将 OnServerValidate 属性设置为验证事件的处理程序的名称。
<asp:CustomValidator id="CustomValidator1" runat="server" ControlToValidate="TextBox1" Display="Dynamic" OnServerValidate="CustomValidation" />
保存并关闭用户控件文件。
如果需要自定义,请打开编辑字段模板的代码隐藏文件并添加自定义。
下面的示例演示如何创建 CustomValidator 控件的服务器代码。代码将用户输入的值与特定的阈值进行比较,如果数据不在允许的范围内,就会显示一条错误消息。
protected void CustomValidation(object source, ServerValidateEventArgs args) { // Check if the input is in the allowed range. bool result = CheckRange(intUnits); // Return result. args.IsValid = result; }
Protected Sub CustomValidation( _ ByVal source As Object, ByVal args As ServerValidateEventArgs) 'Check if the value is in the allowed range. Dim result As Boolean = CheckRange(intUnits) 'Return result. args.IsValid = result End Sub
示例
本示例演示如何使用数据模型,来自定义呈现的用于显示和编辑 SalesOrderDetail 表的 OrderQty 数据字段的 UI。
如果值小于最小警告阈值,CustomFieldTemplate.ascx 字段模板将使用红色前景色来显示订单数量。如果值大于最大警告阈值,它将使用蓝色前景色来显示订单数量。
CustomFieldTemplate_Edit.ascx 字段模板根据范围限制来检查用户输入的 OrderQty 值。如果用户输入的值不在允许的范围内,将显示一条自定义错误消息。
<%@ Page Language="VB"
AutoEventWireup="true" CodeFile="CustomAppearanceBehavior.aspx.vb"
Inherits="CustomAppearanceBehavior" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<link href="~/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h2>Example: <%=Title%></h2>
<!-- Enable dynamic behavior. The GridView must be
registered with the manager. See code-behind file. -->
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server"
AutoLoadForeignKeys="true" />
<form id="form1" runat="server">
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
runat="server" />
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="OrderQty" />
<asp:DynamicField DataField="UnitPrice" />
<asp:DynamicField DataField="ModifiedDate" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource" runat="server"
TableName="SalesOrderDetails" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="CustomAppearanceBehavior.aspx.cs"
Inherits="CustomAppearanceBehavior" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<link href="~/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h2>Example: <%=Title%></h2>
<!-- Enable dynamic behavior. The GridView must be
registered with the manager. See code-behind file. -->
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server"
AutoLoadForeignKeys="true" />
<form id="form1" runat="server">
<!-- Capture validation exceptions -->
<asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1"
runat="server" />
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="GridDataSource"
AutoGenerateColumns="false"
AutoGenerateEditButton="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true">
<Columns>
<asp:DynamicField DataField="OrderQty" />
<asp:DynamicField DataField="UnitPrice" />
<asp:DynamicField DataField="ModifiedDate" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
</form>
<!-- Connect to the database -->
<asp:LinqDataSource ID="GridDataSource" runat="server"
TableName="SalesOrderDetails" EnableUpdate="true"
ContextTypeName="AdventureWorksLTDataContext">
</asp:LinqDataSource>
</body>
</html>
Imports System
Imports System.Collections
Imports System.Configuration
Imports System.Web.DynamicData
Partial Public Class CustomAppearanceBehavior
Inherits System.Web.UI.Page
Protected _table As MetaTable
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
' Register control with the data manager.
DynamicDataManager1.RegisterControl(GridView1)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Get the table entity.
_table = GridDataSource.GetTable()
' Assign title dynamically.
Title = String.Concat( _
"Customize Appearance and Behavior of the ", _
_table.Columns(2).DisplayName, " Data Field")
End Sub
End Class
using System;
using System.Collections;
using System.Configuration;
using System.Web.DynamicData;
public partial class CustomAppearanceBehavior : System.Web.UI.Page
{
protected MetaTable _table;
protected void Page_Init(object sender, EventArgs e)
{
// Register control with the data manager.
DynamicDataManager1.RegisterControl(GridView1);
}
protected void Page_Load(object sender, EventArgs e)
{
// Get the table entity.
_table = GridDataSource.GetTable();
// Assign title dynamically.
Title = string.Concat("Customize Appearance and Behavior of the ",
_table.Columns[2].DisplayName, " Data Field");
}
}
编译代码
若要编译示例代码,需要以下组件:
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。