使用 ASP+ 列表绑定控件 Nikhil Kothari Microsoft Corporation 2000年7月
摘要: 说明 ASP+ Repeater、DataList 和 DataGrid 服务器控件。这些控件能够实现一个根植于数据源的,基于 HTML 的应用程序用户界面。讨论与这些控件有关的概念并概要介绍使用这些控件的基本示例。
目录 简介 列表绑定控件是如何工作的? Repeater 控件 DataList 控件 DataGrid 控件 Repeater、DataList 或 DataGrid? 相关资源 下载与本文相关的示例文件 (56 KB)。
简介 Repeater、DataList 和 DataGrid 控件构成 ASP+ 页面框架中 System.Web.UI.WebControls 名称空间内的相关 Web 控件集。这些控件使 HTML 显示所绑定列表或数据源的内容。因此,将它们统称为“列表绑定控件”。
与框架中的其它 Web 控件类似,这些控件提供一致的编程模型并封装一个独立于浏览器的表示逻辑。这些特性使开发人员能够针对对象模型编程而不用必须掌握与 HTML 相关的那些不一致的和复杂的技术知识。
这三种控件可以按多种布局(包括列表、分栏/报纸栏目和流布局(HTML 流))来表示与其相关的数据源内容。此外,它们还允许您创建完全不同的或完全定制的布局。除了封装有表示逻辑外,还提供了用来处理已发送数据、执行状态管理和引发事件的功能。最后,它们还对诸如选择、编辑、分页和排序之类的标准操作提供不同级别的支持。这些控件可以简化几种常见的 Web 应用程序方案,包括报表、购物车、产品列表、查询结果和导航菜单。
下面几节将进一步说明这些控件和如何在您的 Web 应用程序中使用它们,以及如何选用控件。
列表绑定控件是如何工作的? 本节是本文其余部分的背景材料。概述了这些列表绑定控件的工作方式、它们的共同特性以及某些相关概念。
DataSource 属性 每个控件都有一个 DataSource 属性,其类型为 System.Collections.ICollection。用最简单的话来说,数据源是同类对象的一个列表或集合。
此框架中有几个对象提供了 ICollection 的实现。这个集合包括 System.Data.DataView (它通常用来访问关系数据库和 XML 数据)、一般 ICollection 实现(如 ArrayList 和 Hashtable)以及数组。
与传统的数据绑定控件(它们通常需要 ADO 记录集)不同,除了实现 ICollection 接口之外,这些列表绑定控件未对其数据源强加任何其它要求。根据设计,通过大量增加可作为有效 DataSource 属性值的类型和数据结构,它们能够为您的应用程序代码实现最大程度的简单和灵活性。
项目集合 每个列表绑定控件都包含一个项目集合。控件通过列举这些对象当前的数据源来置入其项目集合。在列举中为每个对象创建单个项目并用于表示该对象。这些项目同时成为列表绑定控件中包含的控件层次结构的一部分。
下表列出了与数据源的数据相关联的项目类型。
项目 创建的默认项目类型 AlternatingItem 为项目集合中具有奇数下标的项目创建 SelectedItem 为选定的项目创建(不论该项目是否为备选项目) EditItem 为处于编辑模式下的项目创建(不管它是否被选中或是否为备选项目)
控件同时创建将在表示中用到的下列项目。但是,它们并不与数据源的数据相关联。
标头 用来表示标头信息 注脚 用来表示注脚信息 分隔符 用来表示图 1 中所示的每个项目之间的内容,并且仅适用于 Repeater 和 DataList 分页符 用来表示与 DataGrid 控件相关联的分页 UI
图 1. 相对于“控件”集合的“项目”集合
项目的数据绑定和创建 列表绑定控件遵循在整个 ASP+ 框架中实现的显式数据绑定模型。这意味着控件仅当其 DataBind 方法被调用时才需要并列举其数据源。
当调用 DataBind 方法时,列表控件将列举其数据源、创建项目并通过从其数据源中提取值来对其进行初始化。如果启用了状态管理,则控件还将保存所需的全部信息,以便在页面的回传处理期间重新创建其项目而无须重新设置数据源。
显式数据绑定模型使您的应用程序代码可以精确地确定在处理序列中何时及何处需要数据源。这种功能使对数据库服务器的访问更少且更高效,而这些访问通常是 Web 应用程序最耗费资源的操作。
一般规则是每当您需要重新创建项目时都必须调用 DataBind。在大多数情况下,您将在您的页面首次被请求创建初始项目集合时调用 DataBind。在该页面的后续执行过程中,您将需要在引起项目集合被更改的各种事件处理程序中调用此方法。当用于创建初始数据源的查询被修改时,就可能发生这种情况。当项目的状态改变(如从只读模式变为编辑模式)时也可能发生这种情况。
样式 通过在对象模型上使用样式属性,您可以定义全部 DataList 和 DataGrid 控件及其所包含项目的格式和外观。这些属性允许定制字体、颜色、边框和其它外观因素。控件本身的样式属性(如前景色、背景色、字体和边框样式)将影响整个控件的表示。
此外,每个控件都包含与其所创建的项目类型相匹配的大量样式属性,如 as ItemStyle、AlternatingItemStyle 和 headerStyle。DataGrid 提供第三级的样式属性,这些属性将影响特定列的所有单元格。控件中包含的每一列都可以拥有其自己的 headerStyle、FooterStyle 和 ItemStyle。
模板 样式控制格式显示,而模板则定义每个项目的内容和表示。您可以将模板看作 HTML 代码片断,它定义了用来表示项目的控件层次结构。
Repeater 和 DataList 控件由您指定的模板来驱动,提供各种可设置的模板属性,如 ItemTemplate、AlternatingItemTemplate 和 headerTemplate。与样式类似,每个模板都对应于一个特定类型的项目。
DataGrid 控件未模板化。但是,控件的 Column 集合中的 TemplateColumns 使 DataGrid 中模板的使用成为可能。TemplateColumn 中的每个单元格都可以包含一个模板,这与 Repeater 或 DataList 控件中的项目极为类似。这也使 DataGrid 中的定制表示成为可能。
模板中的数据绑定 模板定义项目中包含的控件层次结构。通过使用数据绑定表达式,此层次结构中的控件属性可绑定到与此项目相关联的数据属性上。
作为模板的逻辑父级的项目在数据绑定表达式中被称为“容器”。每个容器都有一个称为 DataItem 的属性,该属性引用其相关联的数据。结果是,模板中的大多数典型数据绑定表达式都将控件属性绑定到 Container.DataItem 的某个属性上。将在以下几节介绍的示例中进一步说明这种绑定。
Repeater 控件 如前面所述,Repeater 控件是完全由模板驱动的,允许创建完全可定制的表示和布局。下图说明了这一功能。
图 2. 使用 Repeater 控件生成的带项目符号的链接列表
摘自 Repeater1.aspx:
<%@ Page language="C#" src="Repeater1.cs" inherits="Samples.Repeater1Page"%> ...
<asp:Repeater runat=server id="linksListRepeater" DataSource='<%# SiteLinks %>'> <template name="headerTemplate"> <ul type="1"> </template> <template name="ItemTemplate"> <li> <asp:HyperLink runat=server Text='<%# DataBinder.Eval(Container.DataItem, "SiteName") %>' NavigateUrl='<%# DataBinder.Eval(Container.DataItem, "SiteURL") %>'> </asp:HyperLink> </li> </template> <template name="FooterTemplate"> </ul> </template> </asp:Repeater>
此 .aspx 文件显示了一个用于生成带项目符号列表的 repeater 控件的声明。
此示例说明了用数据绑定语法 (<%#...%>) 设置数据源的声明方法。当您调用 DataBind 方法时,数据绑定中的表达式就会被执行。在这种情况下,repeater 的 DataSource 属性被绑定到页面的 SiteLinks 属性上,后者包含要显示的 URL 引用。
Repeater 是唯一允许在其模板中存在 HTML 片段的控件,将 Repeater 控件和 HTML 片段合在一起会产生良好形式的 HTML。在本示例中,带项目符号的列表分为三个部分:
由 headerTemplate 表示的列表开始标记 (<ul type="1">)。
由 FooterTemplate 表示的列表结束标记 (</ul>)。
列表的主体由通过为 SiteLinks 集合中出现的每个对象重复 ItemTemplate 而生成的列表项 (<li>) 置入。 您也可以使用这些模板在标头中指定表的开始标记 (<TABLE>),在注脚中指定表的结束标记(</TABLE>),在每个项目中指定单个表行 (<TR>)。此替换选项将导致列表表示。
您必须指定 ItemTemplate。它是唯一必需的模板。当未指定其它模板时,控件会自动将此 ItemTemplate 用于其它模板。
在以下示例中,ItemTemplate 包含一个 HyperLink Web 控件。此控件的 Text 和 NavigateUrl 属性被绑定到与每个重复项目相关联的数据属性上。这又是使用数据绑定表达式(在创建项目后立即对该表达式求值)完成的。
Repeater1.cs:
namespace Samples { ...
public class Repeater1Page : Page { protected Repeater linksListRepeater;
public ICollection SiteLinks { get { ArrayList sites = new ArrayList();
sites.Add(new SiteInfo("Microsoft Home", "http://www.microsoft.com")); sites.Add(new SiteInfo("MSDN Home", "http://msdn.microsoft.com")); sites.Add(new SiteInfo("MSN Homepage", "http://www.msn.com")); sites.Add(new SiteInfo("Hotmail", "http://www.hotmail.com")); return sites; } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
if (!IsPostBack) { // 首次请求该页时即对其进行数据绑定 (DataBind)。 // 这将在此页的控件层次结构中递归调用每个控件。 DataBind(); } } }
public sealed class SiteInfo { private string siteName; private string siteURL;
public SiteInfo(string siteName, string siteURL) { this.siteName = siteName; this.siteURL = siteURL; }
public string SiteName { get { return siteName; } } public string SiteURL { get { return siteURL; } } } }
此 .cs 文件包含随前一个列表中的 aspx 页一起出现的代码。
Repeater1Page 类覆盖了 Page 类的 OnLoad 方法。此表示在对该页的首次请求中调用 DataBind。这将导致对这些页上的数据绑定表达式求值并使 repeater 控件列举数据源以及创建其项目。仅在首次请求时调用 DataBind 方法。这之所以能正常工作是因为 repeater 能够在从前一次保存状态的回传过程中重新创建其项目,而无需数据源实例。
此页将类型 ICollection 的公用属性显露出来。这将在设置 repeater 的 DataSource 属性值的数据绑定表达式中使用。属性的获取实现使用包含一组 SiteInfo 对象序列的 ArrayList。此属性是公用的,因为只有页类的公用和保护成员可在数据绑定表达式中使用。
每个 SiteInfo 对象有两个属性:SiteName 和 SiteURL。当对模板中的 HyperLink 控件进行数据绑定时将访问这些属性。在此控件的绑定表达式中,Container.DataItem 表示要将特定项绑定到其上的单个 SiteInfo 对象。DataBinder.Eval(Container.DataItem, "SiteName") 访问当前 SiteInfo 对象的 SiteName 属性。
Repeater1 示例向您介绍了几个基本概念:
定义模板
模板中的数据绑定语法和数据绑定表达式
将 ArrayList 的 ICollection 表示用作数据源
在最初处理页的过程中调用 DataBind 方法 DataList 控件 DataList 控件是一个模板化控件,它提供使用样式属性可视化地格式化其表示的能力。它也可以产生多列布局。图 3 说明了这两种特性。
图 3. 从 DataList 的双列表示生成的示例
摘自 DataList1.aspx:
<%@ Page language="C#" src="DataList1.cs" inherits="Samples.DataList1Page"%> ...
<asp:DataList runat=server id="peopleDataList" RepeatColumns="2" RepeatDirection="Vertical" RepeatMode="Table" Width="100%">
<property name="AlternatingItemStyle"> <asp:TableItemStyle BackColor="#EEEEEE"/> </property> <template name="ItemTemplate"> <asp:Panel runat=server font-size="12pt" font-bold="true"> <%# ((Person)Container.DataItem).Name %> </asp:Panel> <asp:Label runat=server Width="20px" BorderStyle="Solid" BorderWidth="1px" BorderColor="Black" BackColor='<%# ((Person)Container.DataItem).FavoriteColor %>'> </asp:Label> <asp:Label runat=server Font-Size="10pt" Text='<%# GetColorName(((Person)Container.DataItem).FavoriteColor) %>'> </asp:Label> </template> </asp:DataList>
此 .aspx 文件显示了用来生成此示例的 DataList 的声明。
在此示例中,DataList 的多列布局是通过将 RepeatColumns 属性设置为“2”来实现的。将 RepeatDirection 设置为“Vertical”会使项目从上到下、然后从左到右排列。相反,值设置为“Horizontal”会导致项目从左到右、然后从上到下排列。
aspx 语法包含对少数几种 DataList 的样式属性的设置。在此示例中,DataList 的 Width 被设置为其父级的 100%。设置具有灰色背景的 AlternatingItemStyle 是为了获得带有条纹的外观。此示例还说明模板可以包含任意复杂的控件定义,以满足在每个项目内获得理想布局的需要。
最后,此模板中的数据绑定表达式通过将 Container.DataItem 转换为其类型来使用前期绑定。这不会招致与使用 DataBinder.Eval (如 Repeater1 中所示) 相关联的后期绑定的代价。但是,这种方法可能会产生可读性较差的表达式。以下示例还给出了一个调用 GetColorName 方法(该方法是在本页有代码支持的文件中实现的)的表达式示例。
DataList1.cs:
namespace Samples { ...
public class DataList1Page : Page { protected DataList peopleDataList;
protected string GetColorName(Color c) { return TypeDescriptor.GetConverter(typeof(Color)).ConvertToString(c); }
private void LoadPeopleList() { // 创建数据源 Person[] people = new Person[] { new Person("Nikhil Kothari", Color.Green), new Person("Steve Millet", Color.Purple), new Person("Chris Anderson", Color.Blue), new Person("Mike Pope", Color.Orange), new Person("Anthony Moore", Color.Yellow), new Person("Jon Jung", Color.MediumAquamarine), new Person("Susan Warren", Color.SlateBlue), new Person("Izzy Gryko", Color.Red) };
// 设置控件的数据源 peopleDataList.DataSource = people;
// 并使该控件用此数据源构建其项目 peopleDataList.DataBind(); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
if (!IsPostBack) { // 首次请求此页 LoadPeopleList(); } } }
public sealed class Person { private string name; private Color favoriteColor;
public Person(string name, Color favoriteColor) { this.name = name; this.favoriteColor = favoriteColor; }
public Color FavoriteColor { get { return favoriteColor; } } public string Name { get { return name; } } } }
在此页中,控件的 DataSource 属性是通过程序设置的,与在 aspx 文件中声明性地设置相对。两种方法的结果相同。无法选择哪种方法,都必须调用 DataBind 方法,以便控件可以列举其数据源并创建它要表示的项目。
此示例中所用的数据源是 Person 对象的一个简单数组。由于每个数组都实现 ICollection 方法,所以数组适合用作数据源。这显示了将数据结构和类型用作数据源时可获得的灵活程度。
DataList1 示例介绍了下列概念:
在模板中定义丰富的 HTML UI
使用简单数组作为数据源
通过程序设置数据源
数据绑定语法中所允许的各
|