决定何时使用 DataGrid、DataList 或 Repeater

 

斯科特·米切尔

2003 年 7 月

适用于:
    Microsoft® ASP.NET

总结: 了解 ASP。NET 用于显示数据的三个控件:DataGrid、DataList 和 Repeater。 其中每个控件都具有独特的特征以及相关的优缺点。 创建显示数据的 ASP.NET 应用程序时,请务必为作业选择正确的控件。 如本文所述,选择是使用 DataGrid、DataList 还是 Repeater 是三个因素之间的权衡:可用性、开发时间和性能。 ) (12 个打印页

下载 DataControlsPerfTest_Setup.msi

目录

简介
数据 Web 控件之间的相似性
检查 DataGrid Web 控件
分析 DataList
深入了解中继器
结论
基准设置

简介

自简单的基于脚本的 Web 编程技术(如 Microsoft® Active Server Pages) (ASP) 以来,Web 开发已经取得了长篇大头。 借助 Microsoft ASP.NET,许多在经典 ASP 中司空见惯的繁琐、重复的编码工作现在已成为过去。 例如,正如所有一次性经典 ASP 开发人员所知道的,在经典 ASP 网页中显示数据需要以下伪代码:

Create connection to the database
Populate an ADO Recordset with a SQL query

Display any header HTML needed
For Each Record in the Recordset
   Print out the Recordset field(s) and associated HTML
   Move to the next record
Next
Display any footer HTML needed

例如,若要在 HTML <table> 中显示 Recordset 的内容,开发人员必须发出标记的 HTML 标记<table>,然后循环访问 Recordset 中的每条记录,每个循环发出一<tr>个标记,以及她感兴趣的 Recordset 字段的值以及多个<td>标记。 最后,在循环之后,开发人员需要发出结束<table>标记。

经典 ASP 所需的此方法有一个主要缺点:它将 HTML 内容与 ASP 网页的源代码紧密集成。 如果不分离代码和 HTML 内容,对 HTML 内容进行更改会成倍增加,尤其是对于可能不精通编程技术的图形艺术家或 Web 设计师。 此外,这种代码和 HTML 内容的集成需要相对大量的代码,因为检索数据库结果和发出其内容都需要代码。

幸运的是,ASP.NET 提供了三个控件,使在 ASP.NET 网页中显示数据比经典 ASP 中所需的迭代方法简单得多。 这三个控件(我以后将称之为 数据 Web 控件)是 DataGrid、DataList 和 Repeater。 如果你已经开发了 ASP.NET 网页,你可能已经至少使用这三个控件之一。 大多数情况下,开发人员开始了解 DataGrid,因为它易于使用,并且能够对数据进行排序、分页和编辑。 但是,在 ASP.NET 网页中显示数据时,DataGrid 并不总是控件的最佳选择。

在本文中,我们将检查每个数据 Web 控件的独特特征。 这些特征为每个数据 Web 控件提供了许多优缺点。 由于每个数据 Web 控件都有一些缺点,因此任何作业都没有“完美”控件。 在决定使用哪个控件时,必须权衡三个数据 Web 控件中每个控件的优点和缺点,并确定使用的最佳控件是什么。

为了帮助我们进行比较,在检查每个数据 Web 控件时,我们将重点介绍三个指标:可用性 (从 Web 访问者) 、开发时间和性能的角度。 我们将从快速了解三个数据 Web 控件之间的相似性开始。 接下来,我们将深入探讨 DataGrid 的检查,然后转到 DataList,最后查看 Repeater。 对于每个控件,我们将查看控件的功能,并讨论其功能集如何影响这些指标。

数据 Web 控件之间的相似性

在研究数据 Web 控件之间的差异之前,让我们先看一下它们的相似之处。 最普遍的相似之处是,从高级别的角度来看,DataGrid、DataList 和 Repeater 都设计为执行大致相同的操作:显示数据。 另一个相似之处是将数据绑定到数据 Web 控件所需的代码。 具体而言,只需要两行代码:

dataWebControlID.DataSource = someDataSource
dataWebControlID.DataBind()

通常,someDataSource分配给数据 Web 控件DataSource属性的对象将是 DataSet、SqlDataReader、OleDbDataReader 或集合 (,例如 Array、ArrayList 或命名空间) 中的其他System.Collections类。 但是,任何实现 IEnumerable 接口的对象都可以绑定到数据 Web 控件。

方法DataBind()枚举指定 DataSource 的记录。 对于 中的每个 DataSource记录,都会创建一个 并将其追加到数据 Web 控件的 Items 集合中。 数据 Web 控件中的每个项都是类的实例。 用于每个控件项的特定类取决于数据 Web 控件。 例如,DataGrid 中的每个项都是 类的DataGridItem实例,而 Repeater 中的每个项都是 的 RepeaterItem实例。

每个数据 Web 控件对其每个项使用不同的类,因为这些项的呈现方式决定了数据 Web 控件生成的 HTML 标记。 例如,DataGridItem 类派生自TableRow类,这意味着每个DataGridItem类或多或少地呈现为表行。 这很有意义,因为 DataGrid 旨在以表格格式在 HTML<table>标记中显示数据,其中每个项在 HTML <table> 中呈现为单行。 另一方面,中继器旨在允许完全自定义其输出。 因此,RepeaterItem 类不派生自 类TableRow也就不足为奇了。

数据 Web 控件之间的另一个相似之处是,每个控件都能够使用模板提供高度可自定义的输出。 DataList 和 Repeater 控件 必须使用 模板来指定其内容,而 DataGrid 可以选择通过 TemplateColumn 列类型为特定列使用模板 (我们将在下一节“检查 DataGrid Web 控件”中讨论各种 DataGrid 列类型。) 。

最后一个值得注意的比较是,DataGrid 和 DataList 控件都派生自WebControl类,而 Repeater 控件派生自Control类。 类WebControl包含许多美学属性,例如 BackColor ForeColor CssClass BorderStyle等。 这意味着,使用 DataGrid 和 DataList,可以通过它从WebControl类继承的属性来指定样式设置。 但是,中继器没有任何此类样式属性。 正如我们将在“挖掘中继器”部分中讨论的那样,必须在中继器模板中指定中继器输出的任何视觉设置。

检查 DataGrid Web 控件

在三个数据 Web 控件中,DataGrid Web 控件是迄今为止功能最通用的控件,但在自定义控件生成的实际 HTML 标记方面是最不灵活的。 呈现的 HTML 标记中的这种不灵活性是由于 DataGrid 旨在使用 HTML <table> 以表格格式显示数据。 因此,对于绑定到 DataGrid 的每个记录,将创建一个表行 (<tr>) ,并为要显示的记录中的每个字段创建单个表列 (<td>) 。

DataGrid 附带了许多功能,这些功能可以大大提高所显示数据的可用性。 例如,通过将 DataGrid 的AllowSorting属性设置为 True 并仅添加一些源代码,开发人员可以将普通 DataGrid 转换为可按最终用户对数据进行排序的 DataGrid。 此外,只需多做一点工作,开发人员就可以增强 DataGrid,以允许数据分页或内联编辑数据。 这些功能显然增强了 DataGrid 的可用性。

除了在可用性领域的高分外,DataGrid 还提供较短的开发时间。 若要开始使用 DataGrid 在 ASP.NET 网页上显示数据,只需将 DataGrid 添加到网页并编写所需的两行代码:第一行用于将数据绑定到 DataGrid, DataSource第二行用于调用 DataGrid 的方法DataBind()。 显然,随着添加到 DataGrid 的功能数的增加,开发时间也会增加,但将此开发时间与其他数据 Web 控件进行比较。 假设你想要允许对中继器显示的数据进行排序。 添加此类功能肯定是可能的,但与使用 DataGrid 执行相同的操作相比,需要更多的时间和精力。

尽管 DataGrid 的可用性和开发时间分级令人印象深刻,但此控件存在两个固有的缺点。 首先,如前所述,DataGrid 在自定义呈现的 HTML 标记方面非常有限。 是的,可以自定义 DataGrid 的各个行和列的字体、颜色和边框,但事实仍然是,当 DataGrid 显示数据时,它将位于 HTML<table><tr>DataSource,其中每个记录为 ,每个字段都有 。<td>

具体而言,DataGrid 中的每个列都是派生自 类的类的DataGridColumn实例。 有五种内置的 DataGrid 列类型:

  • BoundColumn
  • ButtonColumn
  • EditColumn
  • HyperLinkColumn
  • TemplateColumn

其中每个列类型都提供数据或提供某种接口,以允许用户与 DataGrid 交互。 例如,BoundColumn 将字段的值DataSource显示为纯文本,而 HyperLinkColumn 显示其文本和 URL 部分可以是DataSource字段的超链接。 除了这些内置列类型外,还可以通过创建派生自DataGridColumn类的类来创建自定义 DataGrid 列类型。 (创建自定义 DataGridColumn Class.)

对于各种 DataGrid 列类型,对于 DataGrid 呈现的 HTML 标记不能高度自定义的原因可能没有意义。 请注意,虽然每个 DataGrid 列类型在呈现时发出不同的 HTML,但每一列都包装在一组<td>标记中,每一行都包含在一组<tr>标记中。 因此,即使 TemplateColumn 可用于自定义每行特定列的 HTML 输出,DataGrid 仍将呈现为 HTML<table><tr>,每行和每列都有 。<td> DataGrid 的此限制禁止更创造性地显示数据。 例如,如果要显示每个表行五条记录,则 DataGrid 不是候选项;相反,必须使用 DataList 或 Repeater。 此外,如果希望数据以 HTML 标记(而非 ) <table>显示,则使用 DataGrid 会很顺利。

DataGrid 的第二个缺点是其性能。 在三个数据 Web 控件中,DataGrid 的性能最差。 除此之外,DataGrid 生成的 ViewState(尤其是具有大量行的 DataGrid)可能非常大。 如果只是使用 DataGrid 来显示数据,则可以关闭 ViewState,但在利用 DataGrid 的排序、分页或编辑功能时,这不是一个选项。

为了测量 DataGrid 的性能,我使用了 Microsoft 的免费 Web 应用程序压力工具 (WAST) 。 本文末尾的“基准设置”部分列出了精确的测试条件和 WAST 设置。 此外,用于测试的代码可在本文末尾下载。

Web 应用程序压力工具通过对一组特定 URL 的请求来轰炸 Web 服务器。 对于每个测试,我有一个 URL 在一分钟内一直以最快的速度不断请求。 WAST 报告许多性能指标;我决定专注于每秒请求数,它指示 Web 服务器每秒可以执行 ASP.NET 网页的次数。

针对仅显示数据的简单 DataGrid 运行了两个测试。 具体而言,DataGrid 显示来自 Northwinds 数据库的 Customers 表的四个字段 (Customers 表总共包含 91 个记录。) 。 DataGrid 的AutoGenerateColumns属性设置为 True。 第一个测试将 DataGrid 放置在 web 窗体中, ( <form runat="server">) ,而第二个测试没有。 通过将控件置于 Form 中且不将其属性显式设置为EnableViewStateFalse,该控件使用 ViewState 保留其状态。 创建此 ViewState 条目可能是一个耗时的过程,减少了每秒可处理的总请求数,如图 1 所示。

Aa479015.aspnet-whenusedatawebcontrols-01 (en-us,MSDN.10) .gif

图 1:DataGrid 的每秒请求数

正如我们在检查 DataList 和 Repeater 时看到的那样,这两个控件的性能都比 DataGrid 更好。

分析 DataList

回想一下,DataGrid 呈现为 HTML <table>,每个DataSource记录作为表行 (<tr>) ,每个记录字段作为表列 (<td>) 。 有时,你可能希望更好地控制数据的呈现。 例如,你可能希望在 HTML <table> 中显示数据,但你可能希望每行显示五条记录,而不是每行一条记录。 或者,你可能根本不希望在标记中<table>显示数据,而是让每个元素显示在标记中<span>

DataList 放弃 DataGrid 采用的“列”概念。 而是通过 模板定义 DataList 的显示。 使用模板,开发人员可以同时指定 HTML 语法 和数据绑定语法的组合。 HTML 语法是常规 HTML 标记;数据绑定语法由 <%#%> 标记分隔,用于从用于构造给定 DataList 项的DataSource记录中发出内容。 例如,下面的 ItemTemplate 将显示DataSource字段 CompanyName:

<asp:DataList runat="server" id="myDataList">
  <ItemTemplate>
    <%# DataBinder.Eval(Container.DataItem, "CompanyName") %>
  </ItemTemplate>
</asp:DataList>

除了数据绑定语法之外,模板还可能包含 HTML 标记。 通过更新上述模板,我们可以使其以CompanyName粗体字体显示字段,同时字段ContactName以非粗体字体显示在字段下方CompanyName

  <asp:DataList runat="server" id="myDataList">
  <ItemTemplate>
    <b><%# DataBinder.Eval(Container.DataItem, "CompanyName") %></b>
    <br />
    <%# DataBinder.Eval(Container.DataItem, "ContactName") %>
  </ItemTemplate>
</asp:DataList>

对于 DataList 的 DataSource 中的每条记录,将计算 ItemTemplate 的数据绑定语法。 除 HTML 标记外,数据绑定语法的输出还指定为 DataList 项呈现的 HTML。 除了 ItemTemplate 之外,DataList 还支持其他六个模板,总共七个模板:

  • AlternatingItemTemplate
  • EditItemTemplate
  • FooterTemplate
  • HeaderTemplate
  • ItemTemplate
  • SelectedItemTemplate
  • SeparatorTemplate

请注意,DataGrid 的 TemplateColumn 仅支持四个模板:ItemTemplate、HeaderTemplate、FooterTemplate 和 EditItemTemplate。

默认情况下,DataList 将每个项显示为 HTML <table> 中的一行。 但是,通过设置RepeatColumns属性,可以指定每个表行应显示的 DataList 项数。 除了能够指定每行 HTML <table> 显示多少个 DataList 项外,还可以指定应使用<span>标记而不是<table>标记来显示 DataList 的内容。 DataList 的RepeatLayout属性(可设置为 Table 或 Flow)指示 DataList 中的数据是在 HTML<table>中呈现还是以标记形式<span>呈现。

借助其模板和RepeatColumnsRepeatLayout属性,很明显,与 DataGrid 相比,DataList 允许对呈现的 HTML 标记进行更多的自定义。 这种增加的自定义可能会导致使用 DataList 更便于用户显示数据,因为 DataGrid 的“每个DataSource记录包含一个表行的单个 HTML<table>”模型可能并不总是最适合显示信息。 但是,若要确定 DataList 的可用性,仅检查对 DataGrid 的自定义改进是不够的;我们还必须将 DataGrid 的排序、分页和编辑功能与 DataList 的功能进行比较。

借助其 EditItemIndex 模板和 EditCommand、UpdateCommand 和 CancelCommand 事件,DataList 可以支持内联编辑。 但是,与使用 DataGrid 相比,使用 DataList 添加此类功能需要更多开发时间。 开发时间的这种差异有两个原因:

  • 可通过 EditCommandColumn 列类型在 DataGrid 中创建的“编辑/更新/取消”按钮必须手动添加到 DataList,并且
  • DataGrid BoundColumn 列类型自动将 TextBox Web 控件用于编辑界面,而对于 DataList,必须显式指定通过 EditItemTemplate 编辑的项的编辑接口。

虽然使用 DataList 进行内联编辑并不十分困难,但对 DataList 的数据进行排序和分页时却不能这样说。 虽然此类功能在一些巧妙的编程中绝对是可能的,但将此类功能添加到 DataList 需要大量的开发时间。 因此,如果最终用户必须对数据进行排序和分页,最好选择 DataGrid,而选择 DataList。

DataList 的性能优于 DataGrid 的性能,当 DataList 位于 Web 窗体中时,最明显的是。 图 2 显示了 DataList 上的 Web 应用程序压力工具测试的结果。

Aa479015.aspnet-whenusedatawebcontrols-02 (en-us,MSDN.10) .gif

图 2:DataList 的每秒请求数

如图 2 中的结果所示,当 Web 控件放置在 Web 窗体中时,DataList 性能优于 DataGrid, (从而导致 Web 控件发出其 ViewState) 。

深入了解中继器

Repeater Web 控件在所有三个数据 Web 控件的呈现 HTML 中提供了最大的灵活性。 与 DataGrid 或 DataList 不同,当呈现时,Repeater 会严格发出指定的 HTML 标记,这两者都会自动将其开发人员指定的内容包含在预先确定的 HTML 标记中。 因此,如果希望以 HTML 或一系列<span>标记以外的<table>方式显示数据,则必须使用 Repeater 控件。

使用 Repeater(如 DataList)时,可以使用模板指定标记。 Repeater 包含以下五个模板:

  • AlternatingItemTemplate
  • FooterTemplate
  • HeaderTemplate
  • ItemTemplate
  • SeparatorTemplate

HeaderTemplate 和 FooterTemplate 指定在绑定到 Repeater 的数据之前和之后显示的 HTML 标记。 AlternatingItemTemplate 和 ItemTemplate 指定用于呈现 Repeater 的每条记录的 DataSource HTML 标记和数据绑定语法。 例如,假设你正在将包含员工信息的 DataSet 绑定到 Repeater,并且 DataSet 中的字段之一是 EmployeeName。 如果要在无序列表中显示网页上的员工列表,可以使用以下 Repeater 语法:

<asp:Repeater runat="server" id="rptEmployees">
  <HeaderTemplate>
    <ul>
  </HeaderTemplate>
  <ItemTemplate>
    <li><%# DataBinder.Eval(Container.DataItem, "EmployeeName") %></li>
  </ItemTemplate>
  <FooterTemplate>
    </ul>
  </FooterTemplate>
</asp:Repeater>

Repeater 类不是派生自 类,WebControl如 DataGrid 和 DataList。 因此,Repeater 缺少 DataGrid 和 DataList 共有的样式属性。 归根结底,如果要设置 Repeater 中显示的数据的格式,则必须在 HTML 标记中执行此操作。 例如,在上面的示例中,如果我们想要以粗体字体显示员工姓名,则必须更改 ItemTemplate 以包含 HTML 粗体标记,如下所示:

<ItemTemplate>
  <li><b><%# DataBinder.Eval(Container.DataItem, "EmployeeName")
    %></b></li>
</ItemTemplate>

而使用 DataGrid 或 DataList 时,可以通过将控件的ItemStyle-Font-Bold属性设置为 True,使文本以粗体显示。

Repeater 缺少样式属性可能会大大增加开发时间指标。 例如,假设你决定使用 Repeater 来显示需要加粗、居中且以特定背景色以特定字体形式显示的数据。 虽然可以使用一些 HTML 标记来指定所有这些内容,但这些标记会很快将中继器模板杂乱无章。 这种杂乱使得在以后更改外观要困难得多,尤其是对于处理项目的其他人员,他们不得不杂乱无章地处理 HTML 语法。 将此与指定 DataGrid 或 DataList 的格式进行比较。 使用这两个控件之一,可以通过指定 DataGrid 或 DataList 的样式属性来使模板保持无杂乱无章。 此外,可以使用 Microsoft Visual Studio® .NET 或 ASP.NET Web Matrix 等工具自动设置 DataGrid 和 DataList 的样式属性。

随着开发时间的增加,Repeater 还缺乏任何内置功能来帮助支持数据的分页、编辑或编辑。 由于缺少功能支持,Repeater 在可用性刻度上得分不佳。 当然, 如果你 感兴趣的只是显示没有任何花哨的钟声或哨声的数据,那么中继器在主要减损器中缺乏功能。 我强调“if”一词,因为通常一旦部署了 Web 应用程序,用户就会发现他们需要其他功能,例如排序、分页和编辑。

一个兑换质量的中继器是 -- 毫不奇怪 - 它的性能。 中继器的性能略高于 DataList 的性能,并且明显优于 DataGrid 的性能。 图 3 显示了 Repeater 与 DataGrid 和 DataList 之间每秒可以处理的请求数。

Aa479015.aspnet-whenusedatawebcontrols-03 (en-us,MSDN.10) .gif

图 3:中继器每秒请求数

结论

在 ASP.NET 网页中显示数据时,许多 Web 开发人员选择他们最熟悉的数据 Web 控件,通常为 DataGrid。 但是,这种盲目的决策并不明智,因为没有普遍的“最佳”数据 Web 控件。 相反,在决定 Web 控件用于给定网页的数据时,请问自己各种问题,以确定哪个控件最适合手头的任务。 是否允许用户对数据进行排序? 数据是否需要以 HTML <table> 以外的格式显示? 是否会经常访问此页面,从而使性能成为一个关键问题?

DataGrid Web 控件提供了三个数据 Web 控件中最大的功能集,它允许最终用户对数据进行排序、分页和编辑。 DataGrid 也是最简单的数据 Web 控件,因为使用它只需将 DataGrid 添加到网页并编写几行代码即可。 不过,易用性和令人印象深刻的功能是有代价的,即性能:DataGrid 是三个数据 Web 控件中效率最低的,尤其是在放置在 Web 窗体中时。

与 DataGrid 相比,借助其模板,DataList 可以更好地控制所显示数据的外观。 但是,与使用 DataGrid 的列类型相比,使用模板通常需要更多的开发时间。 DataList 还支持数据的内联编辑,但与 DataGrid 相比,实现所需的工作量要多一些。 遗憾的是,在 DataList 中提供分页和排序支持并非易事。 为了弥补这些缺少内置功能,DataList 比 DataGrid 提供更好的性能。

最后,Repeater 控件允许对呈现的 HTML 标记进行完全和完全控制。 使用 Repeater 时,发出的唯一 HTML 是模板中数据绑定语句的值以及模板中指定的 HTML 标记 - 与 DataGrid 和 DataList 一样,不会发出“额外”HTML。 通过要求开发人员指定完整的生成的 HTML 标记,Repeater 通常需要最长的开发时间。 此外,Repeater 不提供内置的编辑、排序或分页支持。 但是,Repeater 确实拥有三个数据 Web 控件的最佳性能。 其性能与 DataList 相当,但明显优于 DataGrid 的性能。

编程愉快!

基准设置

测试在 Microsoft Windows® 2003 Server 笔记本电脑上运行,该笔记本电脑具有 2.4 GHz Intel Pentium 4 处理器、512 MB RAM 和 30GB Ultra ATA 硬盘驱动器。 使用的 Web 服务器为 IIS 6.0;使用了 ASP.NET 版本 1.1。 Web 应用程序压力工具配置为在其测试中使用单个线程,没有发出预热或冷却请求。 每个测试的持续时间为一分钟。

有关数据 Web 控件的性能测试以及其他出色的 ASP.NET 性能信息的详细信息,检查 TechEd 2003 中的 Scott Guthrie ASP.NET Performance Talk。 此外,你可以从他的演讲中下载 演示

Scott Mitchell 是五本 ASP/ASP.NET 书籍的作者,4GuysFromRolla.com 的创始人,在过去的五年里一直在使用 Microsoft Web 技术。 Scott 是 ASP 和 ASP.NET 社区的活跃成员,对 ASP 和 ASP.NET 充满热情,并乐于帮助其他人详细了解这些令人兴奋的技术。 有关 DataGrid、DataList 和 Repeater 控件的详细信息,检查 Scott 的书籍 ASP.NET Data Web Controls Kick Start Start (ISBN:0672325012) 。

© Microsoft Corporation. 保留所有权利。