关于何种情况下使用DataGrid、DataList或Repeater的一些讨论
生活随笔
收集整理的這篇文章主要介紹了
关于何种情况下使用DataGrid、DataList或Repeater的一些讨论
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
作者:Scott Mitchell
[概述]
WEB開(kāi)發(fā)自從有了基于腳本的WEB編程技術(shù)(如ASP)以來(lái),經(jīng)歷了一個(gè)漫長(zhǎng)的過(guò)程。通過(guò)使用微軟的ASP.Net技術(shù),傳統(tǒng)的ASP中大量的、單調(diào)乏味的、重復(fù)性的編程工作成為了歷史。例如,象大多數(shù)ASP程序員所知的,在ASP中顯示數(shù)據(jù)庫(kù)內(nèi)容所需要的過(guò)程:
建立數(shù)據(jù)庫(kù)連接
用SQL查詢裝載ADO數(shù)據(jù)集
顯示所需要的任何HTML代碼
遍歷數(shù)據(jù)集中的記錄
輸出記錄字段值及相關(guān)的HTML
移向下一條記錄
循環(huán)
顯示所需要的HTML代碼
又如,為了在表格中顯示記錄集的內(nèi)容,我們需要輸出一個(gè)<table>標(biāo)簽,然后開(kāi)始循環(huán)。在循環(huán)中,每輸出一條記錄,需要先輸出一個(gè)<tr>標(biāo)簽以及若干對(duì)<td>標(biāo)簽和</tr>標(biāo)簽。最后,以一個(gè)</table>標(biāo)簽結(jié)尾。
在傳統(tǒng)的ASP中使用的這種方法有一個(gè)主要的缺點(diǎn):HTML代碼與ASP源代碼不得不糾纏在一起。對(duì)于那些也許并不理解程序設(shè)計(jì)的頁(yè)面設(shè)計(jì)者或圖形藝術(shù)家來(lái)說(shuō),想要更改HTML內(nèi)容無(wú)疑是一場(chǎng)災(zāi)難。另外,代碼的產(chǎn)生量也是驚人的,因?yàn)槲覀儾粌H需要從數(shù)據(jù)庫(kù)中取得數(shù)據(jù),還需要使之可視化。
好在,ASP.Net提供了三個(gè)數(shù)據(jù)控件,使得原本在ASP中繁雜的工作變得簡(jiǎn)單。這三個(gè)控件屬于數(shù)據(jù)Web控件,分別是DataGrid,DataList和Repeater。如果你對(duì)ASP.Net數(shù)據(jù)庫(kù)編程有所了解的話,你至少應(yīng)該有使用其中一種控件的經(jīng)驗(yàn)。大多數(shù)情況下,我們從學(xué)習(xí)使用DataGrid開(kāi)始,因?yàn)樗墓δ芟鄬?duì)完整(數(shù)據(jù)顯示、分頁(yè)、編輯)并相對(duì)簡(jiǎn)單。然而,DataGrid并非總是正確的選擇。
本文將分別論述每個(gè)數(shù)據(jù)控件不同于其它數(shù)據(jù)控件的特點(diǎn),以及由此帶來(lái)的優(yōu)缺點(diǎn)。正因?yàn)槊糠N數(shù)據(jù)控件都有其自身的缺陷,因此在程序設(shè)計(jì)中并不存在最完美的選擇。你必須權(quán)衡三種控件的優(yōu)缺點(diǎn)并決定哪一種更加適合你的程序。
為了幫助比較,在對(duì)每個(gè)控件進(jìn)行論述時(shí),我們會(huì)專(zhuān)注于三個(gè)特性:可用性(從頁(yè)面訪問(wèn)者的角度)、開(kāi)發(fā)時(shí)間和性能。我們首先描述一下這三種控件的共性,然后分別深入地討論三種控件的特點(diǎn),每種控件如何實(shí)現(xiàn)以及如何體現(xiàn)可用性、開(kāi)發(fā)時(shí)間和性能。
[數(shù)據(jù)控件(Data Web Controls)的共同點(diǎn)]
在我們討論三種控件各自特性之前,有必要先看一看它們之間的共同點(diǎn)。一般來(lái)說(shuō),從編程流程來(lái)看,最顯著的共同點(diǎn)就是,這三種控件都是用來(lái)顯示數(shù)據(jù)的。另一個(gè)共同點(diǎn)是需要一個(gè)數(shù)據(jù)綁定的代碼來(lái)將數(shù)據(jù)與控件綁定。這個(gè)過(guò)程只需要兩行代碼:
dataWebControlID.DataSource = someDataSource
dataWebControlID.DataBind()
一般情況下,someDataSource對(duì)象是指數(shù)據(jù)控件的數(shù)據(jù)源屬性,可以是DataSet,SqlDataReader,OleDbDataReader或一組數(shù)據(jù)(如數(shù)組、數(shù)組列表或其它的屬于System.Collection名空間的類(lèi))。不過(guò),任意實(shí)現(xiàn)IEnumerable接口的對(duì)象也可以被綁定在數(shù)據(jù)控件上。
DataBind()方法遍歷一個(gè)特定的DataSource中的記錄,并對(duì)其中的每條記錄,建立一個(gè)條目并對(duì)應(yīng)數(shù)據(jù)控件的Item集。數(shù)據(jù)控件中的每個(gè)條目將成為一個(gè)類(lèi)的實(shí)例。這個(gè)類(lèi)因數(shù)據(jù)控件的不同而有所區(qū)別。例如,DataGrid中的每個(gè)條目是DataGridItem類(lèi)的一個(gè)實(shí)例,而Repeater中的條目則是RepeaterItem類(lèi)的一個(gè)實(shí)例。
之所以使用不同的類(lèi)來(lái)實(shí)例化不同數(shù)據(jù)控件的條目,是因?yàn)椴煌臄?shù)據(jù)控件將會(huì)使用不同的方式顯示數(shù)據(jù)及相應(yīng)的HTML代碼。例如,DataGridItem類(lèi)繼承自TableRow類(lèi),也就是說(shuō),每個(gè)DataGridItem的實(shí)例或多或少地可以看成一個(gè)表格中的一行。這是因?yàn)镈ataGrid被設(shè)計(jì)成可以借助HTML中的<table>標(biāo)簽以表格的形式顯示數(shù)據(jù),因此每條記錄就是一個(gè)表格行。而Repeater則被設(shè)計(jì)成可以自由定義數(shù)據(jù)輸出的方式。所以,RepeaterItem并不繼承自TableRow就不奇怪了。
另一個(gè)三種數(shù)據(jù)控件的相同點(diǎn)是每種控件都被允許使用模板來(lái)顯示數(shù)據(jù)。DataList和Repeater控件必須使用模板來(lái)輸出數(shù)據(jù),而DataGrid則允許通過(guò)TemplateColumn而只使用模板來(lái)顯示一列(在DataGrod單元中詳細(xì)論述)。
另一個(gè)不是十分值得比較的地方是:DataGrid和DataList都是繼承自WebControl類(lèi),而Repeater則是繼承自Control類(lèi)。WebControl類(lèi)包含一些用于美化的屬性,如:BackColor、ForeColor、CssClass、BorderStyle等等。這說(shuō)明在使用DataGrid或DataList時(shí),你可以設(shè)定這些屬性來(lái)個(gè)性化輸出。Repeater控件則不具有這些屬性。我們會(huì)在Repeater單元討論如何使用模板來(lái)美化Repeater的輸出。
[DataGrid控件]
在三種控件當(dāng)中,DataGrid是迄今為止功能最為豐富的,但也是最不靈活的控件。這種在輸出HTML時(shí)不夠靈活的特點(diǎn)是因?yàn)樗畛蹙褪潜辉O(shè)計(jì)成以表格的形式輸出數(shù)據(jù)。每一條記錄輸出時(shí)會(huì)建立一對(duì)<tr>標(biāo)簽,而每個(gè)字段的值輸出時(shí)則建立一對(duì)<td>標(biāo)簽。
DataGrid含有幾個(gè)屬性可以提高其可用性。如,通過(guò)設(shè)置DataGrid的AllowSorting屬性為true,并加入少量代碼,DataGrid就具備了按不同字段排序的功能。此外,設(shè)定相關(guān)屬性來(lái)實(shí)現(xiàn)分頁(yè)以及單條記錄編輯的功能更加增強(qiáng)了DataGrid的可用性。
除了在可用性方面的支持以外,DataGrid同時(shí)也相當(dāng)節(jié)省開(kāi)發(fā)時(shí)間。使用DataGrid在WEB頁(yè)面上顯示數(shù)據(jù)只需要兩行代碼。一行用來(lái)設(shè)定與DataGrid綁定的數(shù)據(jù)源(DataSource),另一條則用來(lái)執(zhí)行綁定命令(DataBind())。當(dāng)然,在Repeater中實(shí)現(xiàn)這樣的功能并非不可能,只是,相比較使用DataGrid而言,你需要花費(fèi)相當(dāng)多的時(shí)間和精力來(lái)實(shí)現(xiàn)這些功能。
盡管DataGrid有這樣那樣令人印象深刻的優(yōu)點(diǎn),它的兩個(gè)缺點(diǎn)也同樣不能忽視。首先,如前所述,DataGrid在個(gè)性化輸出數(shù)據(jù)方面功能有限。當(dāng)然,你可以定制字體、顏色以及線條寬度等等,但它始終只能是HTML表格。
每個(gè)在DataGrid中的列都是DataGridColumn類(lèi)的一個(gè)實(shí)例。有五種DataGrid列的形式:
·BoundColumn
·ButtonColumn
·EditColumn
·HyperLinkColumn
·TemplateColumn
每種類(lèi)型都會(huì)以一種方式允許頁(yè)面訪問(wèn)與DataGrid進(jìn)行交互。例如,BoundColumn將DataSource的字段值顯示為純文本;而HyperLinkColumn則將之顯示為一個(gè)超級(jí)鏈接。另外,開(kāi)發(fā)者可以通過(guò)寫(xiě)一個(gè)繼承自DataGridColumn的自定義類(lèi)來(lái)定制DataGrid列的樣式。
盡管DataGrid具有這么多的增強(qiáng)可用性的屬性,卻仍然顯得死板而不夠靈活。這是因?yàn)?#xff0c;不論什么樣的屬性,都需要對(duì)DataGrid所生成的表格進(jìn)行相關(guān)的設(shè)置而生效。這無(wú)疑會(huì)使表格變得臃腫而失去靈活性。例如,DataGridColumn的設(shè)置會(huì)對(duì)表格的每一行的相應(yīng)列生效。DataGrid的這種局限性阻礙了更有創(chuàng)意地顯示數(shù)據(jù)。比如,你希望每五條記錄被顯示在一行,或根本不想要表格來(lái)顯示數(shù)據(jù),你將不得不放棄使用DataGrid。
DataGrid的第二個(gè)缺陷是它的性能。在三種數(shù)據(jù)控件中,DataGrid是相對(duì)性能最差的。由DataGrid所生成的ViewState將會(huì)相當(dāng)龐大,特別是在DataGrid含有較多的行時(shí)。當(dāng)然,你也可以關(guān)閉ViewState功能,但代價(jià)是你將不能使用排序、分頁(yè)以及記錄編輯等功能。
為了測(cè)量DataGrid的性能,我使用了微軟的Web Application Stress Tool (WAST)。精確的測(cè)試條件設(shè)定以及測(cè)試用代碼將會(huì)在本文的結(jié)尾給出。
WAST將會(huì)對(duì)WEB服務(wù)器發(fā)出對(duì)一個(gè)特定URL的請(qǐng)求。每個(gè)測(cè)試將會(huì)針對(duì)一個(gè)URL在一分鐘之內(nèi)連續(xù)不斷地請(qǐng)求。WAST將會(huì)一個(gè)代表性能的數(shù)值,代表WEB服務(wù)器將會(huì)在一秒鐘內(nèi)執(zhí)行ASP.Net頁(yè)面多少次。
兩個(gè)測(cè)試將顯示一個(gè)僅僅顯示數(shù)據(jù)的DataGrid。DataGrid將會(huì)顯示Northwinds數(shù)據(jù)庫(kù)中的Customers表的4個(gè)字段的內(nèi)容(總計(jì)91條記錄)。DataGrid的AutoGenerateColumns屬性將會(huì)被設(shè)為T(mén)rue。第一個(gè)測(cè)試將DataGrid置于一個(gè)Form中,第二個(gè)則不置于Form中。將控件置于Form中而不指定其EnableViewState為False,則控件將會(huì)一直使用ViewState來(lái)維持其狀態(tài)。對(duì)ViewState的設(shè)定是為了有一個(gè)耗時(shí)的處理過(guò)程,來(lái)看一下它對(duì)于每秒種的頁(yè)面請(qǐng)求有什么樣的影響。測(cè)試結(jié)果見(jiàn)圖1。
圖1:對(duì)DataGrid的每秒請(qǐng)求次數(shù)
在下面我們要討論并測(cè)試的DataList和Repeater中,我們會(huì)看到它們的性能將優(yōu)于DataGrid。
[DataList控件]
如前所述,DataGrid使用表格來(lái)顯示數(shù)據(jù)。你也許需要更進(jìn)一步地控制數(shù)據(jù)的顯示。例如,你想使數(shù)據(jù)在表格中顯示,但不是每行只有一條記錄,而是多條。又或者,你并不想使用表格來(lái)顯示數(shù)據(jù),而是只將它們顯示在一系列<span>標(biāo)簽中。
DataList放棄了DataGrid中列表顯示數(shù)據(jù)的概念,而是使用事先定義好的模板(Template)來(lái)定制顯示。通過(guò)使用模板,可以同時(shí)使用HTML標(biāo)簽或數(shù)據(jù)綁定。這里的數(shù)據(jù)綁定的形式為:<%# … %>,用來(lái)顯示數(shù)據(jù)源中給定條目的數(shù)據(jù)記錄。如下的ItemTemplate將會(huì)顯示數(shù)據(jù)源中CompanyName字段:
?? <asp:DataList runat="server" id="myDataList">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CompanyName") %>
</ItemTemplate>
</asp:DataList>
通過(guò)修改上面的模板,我們可以使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>
對(duì)于DataList數(shù)據(jù)源中的每一條記錄,ItemTemplate會(huì)通過(guò)定義HTML標(biāo)簽來(lái)以相同的樣式顯示數(shù)據(jù)。ItemTemplate還支持其它其它6種模板:
·AlternatingItemTemplate
·EditItemTemplate
·FooterTemplate
·HeaderTemplate
·ItemTemplate
·SelectedItemTemplate
·SeparatorTemplate
默認(rèn)情況下DataList會(huì)將記錄顯示在HTML表格中。然而,通過(guò)設(shè)定RepeatColumn屬性,你可以設(shè)置在一行中顯示多少條記錄。更進(jìn)一步,你甚至可以指定DatList的內(nèi)容不顯示在表格中,而是<span>標(biāo)簽中。這可以通過(guò)設(shè)定RepearLayout屬性來(lái)實(shí)現(xiàn)。
通過(guò)模板、RepeatColumn和RepeatLayout屬性,很明顯DataList在定制數(shù)據(jù)輸出樣式方面較DataGrid更具靈活性,使得用戶界面設(shè)計(jì)可以更加友好。當(dāng)然,我們還需要進(jìn)行功能性的對(duì)比,如分頁(yè)、排序、記錄編輯等等。
通過(guò)EditItemIndex模板和EditCommand,UpdateCommand以及CancelCommand事件,DataList將支持記錄編輯的功能。不過(guò),比較DataGrid而言,這需要耗費(fèi)更多的開(kāi)發(fā)時(shí)間來(lái)實(shí)現(xiàn)。這種開(kāi)發(fā)時(shí)間上的不一致主要有兩個(gè)原因:
·編輯/更新/刪除按鈕在DataGrid中可以通過(guò)設(shè)定EditCommandColumn來(lái)自動(dòng)添加;而在DataList中則需要手動(dòng)添加。
·DataGrid的BoundColumn列樣式自動(dòng)使用文本框控件來(lái)顯示記錄編輯界面。而在DataList中,你必須通過(guò)EditItemTemplate明確地指定使用什么樣的編輯界面。
實(shí)現(xiàn)DataList中的分頁(yè)、排序功能同記錄編輯功能情況一樣,并不算非常復(fù)雜。這些功能可以通過(guò)巧妙的編程加以實(shí)現(xiàn),只是耗費(fèi)一些開(kāi)發(fā)時(shí)間。所以,如果需要用戶對(duì)數(shù)據(jù)記錄進(jìn)行排序或編輯的話,使用DataGrid要比使用DataList方便得多。
DataList的性能要比DataGrid好一些,特別是當(dāng)DataList被包含在Form當(dāng)中時(shí)。圖2顯示了WAST對(duì)DataList的測(cè)試。
圖2:對(duì)DataList的每秒請(qǐng)求次數(shù)
可以看出,在被Web Form包含的情況下,DataList的性能要明顯好于DataGrid。
[Repeater控件]
Repeater控件是三種數(shù)據(jù)控件中在HTML輸出方面最為靈活的控件。Repeater會(huì)按照你所要求的樣式嚴(yán)格地輸出數(shù)據(jù)記錄。所以,如果你不想以表格方式或者簡(jiǎn)單的<span>輸出數(shù)據(jù),那么最好使用Repeater。
與DataList一樣,Repeater使用模板來(lái)指定輸出樣式。Repeater支持如下五種模板:
·AlternatingItemTemplate
·FooterTemplate
·HeaderTemplate
·ItemTemplate
·SeparatorTemplate
HederTemplate和FooterTemplate指定在真正的記錄輸出之前或之后應(yīng)處理的HTML內(nèi)容。AlternatingItemTemplate和ItemTemplate則指定實(shí)際的每條輸出記錄的HTML樣式。如,你需要綁定一個(gè)包含雇員信息的DataSet到一個(gè)Repeater,字段名為EmployeeName。如果你想在頁(yè)面中不排序地顯示這些記錄,你可以使用如下的語(yǔ)句:
<asp:Repeater runat="server" id="rptEmployees">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><%# DataBinder.Eval(Container.DataItem, "EmployeeName") %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
Repeater類(lèi)不是繼承自WebControl類(lèi)的,這一點(diǎn)與DataGrid和DataList不同。所以,Repeater沒(méi)有樣式方面的屬性可供設(shè)定。也就是說(shuō),如果你想格式化輸出Repeater的數(shù)據(jù)記錄,你必須使用HTML標(biāo)簽來(lái)設(shè)定樣式。如,在一例中,如果我們想將雇員名字顯示成粗體,我們必須在ItemTemplate設(shè)置相應(yīng)的HTML標(biāo)簽:
<ItemTemplate>
<li><b><%# DataBinder.Eval(Container.DataItem, "EmployeeName")%></b></li>
</ItemTemplate>
而如果使用DataGrid或DataList,我們只通過(guò)設(shè)定ItemStyle-Font-Bold屬性為T(mén)rue即可實(shí)現(xiàn)。
Repeater在格式化設(shè)定上的欠缺,直接反映到開(kāi)發(fā)時(shí)間的延長(zhǎng)上來(lái)。對(duì)輸出數(shù)據(jù)樣式上的越多要求,就越會(huì)導(dǎo)致開(kāi)發(fā)周期的延長(zhǎng)。這些在模板中規(guī)定樣式的HTML標(biāo)簽也越發(fā)得顯得混亂,而且,在將來(lái)頁(yè)面更改時(shí)會(huì)更加困難,特別是當(dāng)一個(gè)新的開(kāi)發(fā)人員接替工作時(shí)。而使用DataGrid或DataList你盡可以只設(shè)定樣式屬性,而不使用模板。而且,如果使用Visual Studio.Net或ASP.Net Web Matrix工作時(shí),這些屬性更可以被直接設(shè)定而無(wú)需編碼。
因?yàn)镽epeater開(kāi)發(fā)時(shí)間的延長(zhǎng),其在內(nèi)建功能(分頁(yè)、排序及編輯)上的支持也顯得不足。因此在可用性方面,Repeater有著明顯的缺陷。當(dāng)然,<b>如果</b>用戶對(duì)于如何顯示數(shù)據(jù)無(wú)所謂的話,這也算不了什么大問(wèn)題。我之所以強(qiáng)調(diào)這個(gè)“如果”,是因?yàn)楸M管用戶有時(shí)在設(shè)計(jì)時(shí)并不要求能夠分頁(yè)、排序或編輯記錄,但這樣的要求往往會(huì)在開(kāi)發(fā)后期,或在他們能看到顯示出來(lái)的記錄后產(chǎn)生。
Repeater唯一優(yōu)于DataGrid和DataList的特點(diǎn)是它的性能,尤其明顯優(yōu)于DataGrid。而比DataList略高一點(diǎn)點(diǎn)。
[結(jié)論]
在ASP.Net頁(yè)面上顯示數(shù)據(jù)時(shí),多數(shù)的程序員會(huì)選擇他們所熟悉的控件來(lái)使用,特別是DataGrid。然而,這樣盲目的選擇在沒(méi)有“最好的通用控件”的情況下是不明智的。在選擇控件來(lái)顯示數(shù)據(jù)前,不妨問(wèn)自己幾個(gè)問(wèn)題來(lái)幫助決策:是否允許用戶對(duì)記錄排序?是不是記錄需要顯示在非表格的情況下?頁(yè)面是否會(huì)被高頻度地訪問(wèn),因此應(yīng)多考慮性能?
DataGrid提供了最多的功能,如允許訪問(wèn)者對(duì)記錄編輯、排序或分頁(yè)。同時(shí)它也是最容易使用的,甚至于簡(jiǎn)單到只需要將之添加到頁(yè)面中而不必額外編寫(xiě)代碼。不過(guò)這些易用性是以性能的損失為代價(jià)的。DataGrid在三種控件中是效率最低的,特別是在使用Web Form的情況下。
通過(guò)使用模板,DataList提供了比DataGrid更加優(yōu)秀的界面效果。不過(guò)這需要以犧牲一定的開(kāi)發(fā)時(shí)間為代價(jià)。為了添加排序、分頁(yè)和編輯功能,程序員不得不花費(fèi)比使用DataGrid更多的精力來(lái)進(jìn)行編碼,雖然它的性能要優(yōu)于DataGrid。
最后,Repeater允許對(duì)數(shù)據(jù)記錄作最大限度的HTML定制。通常,使用Repeater來(lái)顯示數(shù)據(jù)記錄比使用DataGrid和DataList要耗費(fèi)更長(zhǎng)的開(kāi)發(fā)時(shí)間。另外,它不支持內(nèi)建的編輯、排序和分頁(yè)功能。所幸的是,Repeater在性能上要優(yōu)于其它兩種控件,特別是明顯優(yōu)于DataGrid。
[附錄]
WAST測(cè)試設(shè)定
測(cè)試是在運(yùn)行Microsoft Windows 2003 Server操作系統(tǒng)的筆記本電腦上完成的。基本配置如下:Intel P4 2.4G CPU;512 MB RAM;30GB Ultra ATA Hard drive;網(wǎng)頁(yè)服務(wù)器使用IIS 6.0;ASP.Net版本為1.1。此測(cè)試中的WAST被設(shè)置成使用單線程,每個(gè)測(cè)試時(shí)間為一分鐘。
測(cè)試代碼http://download.microsoft.com/download/9/e/9/9e97b2f8-b317-4751-9ac1-2e34eebec26a/DataControlsPerfTest_Setup.msi點(diǎn)擊此處下載
[概述]
WEB開(kāi)發(fā)自從有了基于腳本的WEB編程技術(shù)(如ASP)以來(lái),經(jīng)歷了一個(gè)漫長(zhǎng)的過(guò)程。通過(guò)使用微軟的ASP.Net技術(shù),傳統(tǒng)的ASP中大量的、單調(diào)乏味的、重復(fù)性的編程工作成為了歷史。例如,象大多數(shù)ASP程序員所知的,在ASP中顯示數(shù)據(jù)庫(kù)內(nèi)容所需要的過(guò)程:
建立數(shù)據(jù)庫(kù)連接
用SQL查詢裝載ADO數(shù)據(jù)集
顯示所需要的任何HTML代碼
遍歷數(shù)據(jù)集中的記錄
輸出記錄字段值及相關(guān)的HTML
移向下一條記錄
循環(huán)
顯示所需要的HTML代碼
又如,為了在表格中顯示記錄集的內(nèi)容,我們需要輸出一個(gè)<table>標(biāo)簽,然后開(kāi)始循環(huán)。在循環(huán)中,每輸出一條記錄,需要先輸出一個(gè)<tr>標(biāo)簽以及若干對(duì)<td>標(biāo)簽和</tr>標(biāo)簽。最后,以一個(gè)</table>標(biāo)簽結(jié)尾。
在傳統(tǒng)的ASP中使用的這種方法有一個(gè)主要的缺點(diǎn):HTML代碼與ASP源代碼不得不糾纏在一起。對(duì)于那些也許并不理解程序設(shè)計(jì)的頁(yè)面設(shè)計(jì)者或圖形藝術(shù)家來(lái)說(shuō),想要更改HTML內(nèi)容無(wú)疑是一場(chǎng)災(zāi)難。另外,代碼的產(chǎn)生量也是驚人的,因?yàn)槲覀儾粌H需要從數(shù)據(jù)庫(kù)中取得數(shù)據(jù),還需要使之可視化。
好在,ASP.Net提供了三個(gè)數(shù)據(jù)控件,使得原本在ASP中繁雜的工作變得簡(jiǎn)單。這三個(gè)控件屬于數(shù)據(jù)Web控件,分別是DataGrid,DataList和Repeater。如果你對(duì)ASP.Net數(shù)據(jù)庫(kù)編程有所了解的話,你至少應(yīng)該有使用其中一種控件的經(jīng)驗(yàn)。大多數(shù)情況下,我們從學(xué)習(xí)使用DataGrid開(kāi)始,因?yàn)樗墓δ芟鄬?duì)完整(數(shù)據(jù)顯示、分頁(yè)、編輯)并相對(duì)簡(jiǎn)單。然而,DataGrid并非總是正確的選擇。
本文將分別論述每個(gè)數(shù)據(jù)控件不同于其它數(shù)據(jù)控件的特點(diǎn),以及由此帶來(lái)的優(yōu)缺點(diǎn)。正因?yàn)槊糠N數(shù)據(jù)控件都有其自身的缺陷,因此在程序設(shè)計(jì)中并不存在最完美的選擇。你必須權(quán)衡三種控件的優(yōu)缺點(diǎn)并決定哪一種更加適合你的程序。
為了幫助比較,在對(duì)每個(gè)控件進(jìn)行論述時(shí),我們會(huì)專(zhuān)注于三個(gè)特性:可用性(從頁(yè)面訪問(wèn)者的角度)、開(kāi)發(fā)時(shí)間和性能。我們首先描述一下這三種控件的共性,然后分別深入地討論三種控件的特點(diǎn),每種控件如何實(shí)現(xiàn)以及如何體現(xiàn)可用性、開(kāi)發(fā)時(shí)間和性能。
[數(shù)據(jù)控件(Data Web Controls)的共同點(diǎn)]
在我們討論三種控件各自特性之前,有必要先看一看它們之間的共同點(diǎn)。一般來(lái)說(shuō),從編程流程來(lái)看,最顯著的共同點(diǎn)就是,這三種控件都是用來(lái)顯示數(shù)據(jù)的。另一個(gè)共同點(diǎn)是需要一個(gè)數(shù)據(jù)綁定的代碼來(lái)將數(shù)據(jù)與控件綁定。這個(gè)過(guò)程只需要兩行代碼:
dataWebControlID.DataSource = someDataSource
dataWebControlID.DataBind()
一般情況下,someDataSource對(duì)象是指數(shù)據(jù)控件的數(shù)據(jù)源屬性,可以是DataSet,SqlDataReader,OleDbDataReader或一組數(shù)據(jù)(如數(shù)組、數(shù)組列表或其它的屬于System.Collection名空間的類(lèi))。不過(guò),任意實(shí)現(xiàn)IEnumerable接口的對(duì)象也可以被綁定在數(shù)據(jù)控件上。
DataBind()方法遍歷一個(gè)特定的DataSource中的記錄,并對(duì)其中的每條記錄,建立一個(gè)條目并對(duì)應(yīng)數(shù)據(jù)控件的Item集。數(shù)據(jù)控件中的每個(gè)條目將成為一個(gè)類(lèi)的實(shí)例。這個(gè)類(lèi)因數(shù)據(jù)控件的不同而有所區(qū)別。例如,DataGrid中的每個(gè)條目是DataGridItem類(lèi)的一個(gè)實(shí)例,而Repeater中的條目則是RepeaterItem類(lèi)的一個(gè)實(shí)例。
之所以使用不同的類(lèi)來(lái)實(shí)例化不同數(shù)據(jù)控件的條目,是因?yàn)椴煌臄?shù)據(jù)控件將會(huì)使用不同的方式顯示數(shù)據(jù)及相應(yīng)的HTML代碼。例如,DataGridItem類(lèi)繼承自TableRow類(lèi),也就是說(shuō),每個(gè)DataGridItem的實(shí)例或多或少地可以看成一個(gè)表格中的一行。這是因?yàn)镈ataGrid被設(shè)計(jì)成可以借助HTML中的<table>標(biāo)簽以表格的形式顯示數(shù)據(jù),因此每條記錄就是一個(gè)表格行。而Repeater則被設(shè)計(jì)成可以自由定義數(shù)據(jù)輸出的方式。所以,RepeaterItem并不繼承自TableRow就不奇怪了。
另一個(gè)三種數(shù)據(jù)控件的相同點(diǎn)是每種控件都被允許使用模板來(lái)顯示數(shù)據(jù)。DataList和Repeater控件必須使用模板來(lái)輸出數(shù)據(jù),而DataGrid則允許通過(guò)TemplateColumn而只使用模板來(lái)顯示一列(在DataGrod單元中詳細(xì)論述)。
另一個(gè)不是十分值得比較的地方是:DataGrid和DataList都是繼承自WebControl類(lèi),而Repeater則是繼承自Control類(lèi)。WebControl類(lèi)包含一些用于美化的屬性,如:BackColor、ForeColor、CssClass、BorderStyle等等。這說(shuō)明在使用DataGrid或DataList時(shí),你可以設(shè)定這些屬性來(lái)個(gè)性化輸出。Repeater控件則不具有這些屬性。我們會(huì)在Repeater單元討論如何使用模板來(lái)美化Repeater的輸出。
[DataGrid控件]
在三種控件當(dāng)中,DataGrid是迄今為止功能最為豐富的,但也是最不靈活的控件。這種在輸出HTML時(shí)不夠靈活的特點(diǎn)是因?yàn)樗畛蹙褪潜辉O(shè)計(jì)成以表格的形式輸出數(shù)據(jù)。每一條記錄輸出時(shí)會(huì)建立一對(duì)<tr>標(biāo)簽,而每個(gè)字段的值輸出時(shí)則建立一對(duì)<td>標(biāo)簽。
DataGrid含有幾個(gè)屬性可以提高其可用性。如,通過(guò)設(shè)置DataGrid的AllowSorting屬性為true,并加入少量代碼,DataGrid就具備了按不同字段排序的功能。此外,設(shè)定相關(guān)屬性來(lái)實(shí)現(xiàn)分頁(yè)以及單條記錄編輯的功能更加增強(qiáng)了DataGrid的可用性。
除了在可用性方面的支持以外,DataGrid同時(shí)也相當(dāng)節(jié)省開(kāi)發(fā)時(shí)間。使用DataGrid在WEB頁(yè)面上顯示數(shù)據(jù)只需要兩行代碼。一行用來(lái)設(shè)定與DataGrid綁定的數(shù)據(jù)源(DataSource),另一條則用來(lái)執(zhí)行綁定命令(DataBind())。當(dāng)然,在Repeater中實(shí)現(xiàn)這樣的功能并非不可能,只是,相比較使用DataGrid而言,你需要花費(fèi)相當(dāng)多的時(shí)間和精力來(lái)實(shí)現(xiàn)這些功能。
盡管DataGrid有這樣那樣令人印象深刻的優(yōu)點(diǎn),它的兩個(gè)缺點(diǎn)也同樣不能忽視。首先,如前所述,DataGrid在個(gè)性化輸出數(shù)據(jù)方面功能有限。當(dāng)然,你可以定制字體、顏色以及線條寬度等等,但它始終只能是HTML表格。
每個(gè)在DataGrid中的列都是DataGridColumn類(lèi)的一個(gè)實(shí)例。有五種DataGrid列的形式:
·BoundColumn
·ButtonColumn
·EditColumn
·HyperLinkColumn
·TemplateColumn
每種類(lèi)型都會(huì)以一種方式允許頁(yè)面訪問(wèn)與DataGrid進(jìn)行交互。例如,BoundColumn將DataSource的字段值顯示為純文本;而HyperLinkColumn則將之顯示為一個(gè)超級(jí)鏈接。另外,開(kāi)發(fā)者可以通過(guò)寫(xiě)一個(gè)繼承自DataGridColumn的自定義類(lèi)來(lái)定制DataGrid列的樣式。
盡管DataGrid具有這么多的增強(qiáng)可用性的屬性,卻仍然顯得死板而不夠靈活。這是因?yàn)?#xff0c;不論什么樣的屬性,都需要對(duì)DataGrid所生成的表格進(jìn)行相關(guān)的設(shè)置而生效。這無(wú)疑會(huì)使表格變得臃腫而失去靈活性。例如,DataGridColumn的設(shè)置會(huì)對(duì)表格的每一行的相應(yīng)列生效。DataGrid的這種局限性阻礙了更有創(chuàng)意地顯示數(shù)據(jù)。比如,你希望每五條記錄被顯示在一行,或根本不想要表格來(lái)顯示數(shù)據(jù),你將不得不放棄使用DataGrid。
DataGrid的第二個(gè)缺陷是它的性能。在三種數(shù)據(jù)控件中,DataGrid是相對(duì)性能最差的。由DataGrid所生成的ViewState將會(huì)相當(dāng)龐大,特別是在DataGrid含有較多的行時(shí)。當(dāng)然,你也可以關(guān)閉ViewState功能,但代價(jià)是你將不能使用排序、分頁(yè)以及記錄編輯等功能。
為了測(cè)量DataGrid的性能,我使用了微軟的Web Application Stress Tool (WAST)。精確的測(cè)試條件設(shè)定以及測(cè)試用代碼將會(huì)在本文的結(jié)尾給出。
WAST將會(huì)對(duì)WEB服務(wù)器發(fā)出對(duì)一個(gè)特定URL的請(qǐng)求。每個(gè)測(cè)試將會(huì)針對(duì)一個(gè)URL在一分鐘之內(nèi)連續(xù)不斷地請(qǐng)求。WAST將會(huì)一個(gè)代表性能的數(shù)值,代表WEB服務(wù)器將會(huì)在一秒鐘內(nèi)執(zhí)行ASP.Net頁(yè)面多少次。
兩個(gè)測(cè)試將顯示一個(gè)僅僅顯示數(shù)據(jù)的DataGrid。DataGrid將會(huì)顯示Northwinds數(shù)據(jù)庫(kù)中的Customers表的4個(gè)字段的內(nèi)容(總計(jì)91條記錄)。DataGrid的AutoGenerateColumns屬性將會(huì)被設(shè)為T(mén)rue。第一個(gè)測(cè)試將DataGrid置于一個(gè)Form中,第二個(gè)則不置于Form中。將控件置于Form中而不指定其EnableViewState為False,則控件將會(huì)一直使用ViewState來(lái)維持其狀態(tài)。對(duì)ViewState的設(shè)定是為了有一個(gè)耗時(shí)的處理過(guò)程,來(lái)看一下它對(duì)于每秒種的頁(yè)面請(qǐng)求有什么樣的影響。測(cè)試結(jié)果見(jiàn)圖1。
圖1:對(duì)DataGrid的每秒請(qǐng)求次數(shù)
在下面我們要討論并測(cè)試的DataList和Repeater中,我們會(huì)看到它們的性能將優(yōu)于DataGrid。
[DataList控件]
如前所述,DataGrid使用表格來(lái)顯示數(shù)據(jù)。你也許需要更進(jìn)一步地控制數(shù)據(jù)的顯示。例如,你想使數(shù)據(jù)在表格中顯示,但不是每行只有一條記錄,而是多條。又或者,你并不想使用表格來(lái)顯示數(shù)據(jù),而是只將它們顯示在一系列<span>標(biāo)簽中。
DataList放棄了DataGrid中列表顯示數(shù)據(jù)的概念,而是使用事先定義好的模板(Template)來(lái)定制顯示。通過(guò)使用模板,可以同時(shí)使用HTML標(biāo)簽或數(shù)據(jù)綁定。這里的數(shù)據(jù)綁定的形式為:<%# … %>,用來(lái)顯示數(shù)據(jù)源中給定條目的數(shù)據(jù)記錄。如下的ItemTemplate將會(huì)顯示數(shù)據(jù)源中CompanyName字段:
?? <asp:DataList runat="server" id="myDataList">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "CompanyName") %>
</ItemTemplate>
</asp:DataList>
通過(guò)修改上面的模板,我們可以使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>
對(duì)于DataList數(shù)據(jù)源中的每一條記錄,ItemTemplate會(huì)通過(guò)定義HTML標(biāo)簽來(lái)以相同的樣式顯示數(shù)據(jù)。ItemTemplate還支持其它其它6種模板:
·AlternatingItemTemplate
·EditItemTemplate
·FooterTemplate
·HeaderTemplate
·ItemTemplate
·SelectedItemTemplate
·SeparatorTemplate
默認(rèn)情況下DataList會(huì)將記錄顯示在HTML表格中。然而,通過(guò)設(shè)定RepeatColumn屬性,你可以設(shè)置在一行中顯示多少條記錄。更進(jìn)一步,你甚至可以指定DatList的內(nèi)容不顯示在表格中,而是<span>標(biāo)簽中。這可以通過(guò)設(shè)定RepearLayout屬性來(lái)實(shí)現(xiàn)。
通過(guò)模板、RepeatColumn和RepeatLayout屬性,很明顯DataList在定制數(shù)據(jù)輸出樣式方面較DataGrid更具靈活性,使得用戶界面設(shè)計(jì)可以更加友好。當(dāng)然,我們還需要進(jìn)行功能性的對(duì)比,如分頁(yè)、排序、記錄編輯等等。
通過(guò)EditItemIndex模板和EditCommand,UpdateCommand以及CancelCommand事件,DataList將支持記錄編輯的功能。不過(guò),比較DataGrid而言,這需要耗費(fèi)更多的開(kāi)發(fā)時(shí)間來(lái)實(shí)現(xiàn)。這種開(kāi)發(fā)時(shí)間上的不一致主要有兩個(gè)原因:
·編輯/更新/刪除按鈕在DataGrid中可以通過(guò)設(shè)定EditCommandColumn來(lái)自動(dòng)添加;而在DataList中則需要手動(dòng)添加。
·DataGrid的BoundColumn列樣式自動(dòng)使用文本框控件來(lái)顯示記錄編輯界面。而在DataList中,你必須通過(guò)EditItemTemplate明確地指定使用什么樣的編輯界面。
實(shí)現(xiàn)DataList中的分頁(yè)、排序功能同記錄編輯功能情況一樣,并不算非常復(fù)雜。這些功能可以通過(guò)巧妙的編程加以實(shí)現(xiàn),只是耗費(fèi)一些開(kāi)發(fā)時(shí)間。所以,如果需要用戶對(duì)數(shù)據(jù)記錄進(jìn)行排序或編輯的話,使用DataGrid要比使用DataList方便得多。
DataList的性能要比DataGrid好一些,特別是當(dāng)DataList被包含在Form當(dāng)中時(shí)。圖2顯示了WAST對(duì)DataList的測(cè)試。
圖2:對(duì)DataList的每秒請(qǐng)求次數(shù)
可以看出,在被Web Form包含的情況下,DataList的性能要明顯好于DataGrid。
[Repeater控件]
Repeater控件是三種數(shù)據(jù)控件中在HTML輸出方面最為靈活的控件。Repeater會(huì)按照你所要求的樣式嚴(yán)格地輸出數(shù)據(jù)記錄。所以,如果你不想以表格方式或者簡(jiǎn)單的<span>輸出數(shù)據(jù),那么最好使用Repeater。
與DataList一樣,Repeater使用模板來(lái)指定輸出樣式。Repeater支持如下五種模板:
·AlternatingItemTemplate
·FooterTemplate
·HeaderTemplate
·ItemTemplate
·SeparatorTemplate
HederTemplate和FooterTemplate指定在真正的記錄輸出之前或之后應(yīng)處理的HTML內(nèi)容。AlternatingItemTemplate和ItemTemplate則指定實(shí)際的每條輸出記錄的HTML樣式。如,你需要綁定一個(gè)包含雇員信息的DataSet到一個(gè)Repeater,字段名為EmployeeName。如果你想在頁(yè)面中不排序地顯示這些記錄,你可以使用如下的語(yǔ)句:
<asp:Repeater runat="server" id="rptEmployees">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><%# DataBinder.Eval(Container.DataItem, "EmployeeName") %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
Repeater類(lèi)不是繼承自WebControl類(lèi)的,這一點(diǎn)與DataGrid和DataList不同。所以,Repeater沒(méi)有樣式方面的屬性可供設(shè)定。也就是說(shuō),如果你想格式化輸出Repeater的數(shù)據(jù)記錄,你必須使用HTML標(biāo)簽來(lái)設(shè)定樣式。如,在一例中,如果我們想將雇員名字顯示成粗體,我們必須在ItemTemplate設(shè)置相應(yīng)的HTML標(biāo)簽:
<ItemTemplate>
<li><b><%# DataBinder.Eval(Container.DataItem, "EmployeeName")%></b></li>
</ItemTemplate>
而如果使用DataGrid或DataList,我們只通過(guò)設(shè)定ItemStyle-Font-Bold屬性為T(mén)rue即可實(shí)現(xiàn)。
Repeater在格式化設(shè)定上的欠缺,直接反映到開(kāi)發(fā)時(shí)間的延長(zhǎng)上來(lái)。對(duì)輸出數(shù)據(jù)樣式上的越多要求,就越會(huì)導(dǎo)致開(kāi)發(fā)周期的延長(zhǎng)。這些在模板中規(guī)定樣式的HTML標(biāo)簽也越發(fā)得顯得混亂,而且,在將來(lái)頁(yè)面更改時(shí)會(huì)更加困難,特別是當(dāng)一個(gè)新的開(kāi)發(fā)人員接替工作時(shí)。而使用DataGrid或DataList你盡可以只設(shè)定樣式屬性,而不使用模板。而且,如果使用Visual Studio.Net或ASP.Net Web Matrix工作時(shí),這些屬性更可以被直接設(shè)定而無(wú)需編碼。
因?yàn)镽epeater開(kāi)發(fā)時(shí)間的延長(zhǎng),其在內(nèi)建功能(分頁(yè)、排序及編輯)上的支持也顯得不足。因此在可用性方面,Repeater有著明顯的缺陷。當(dāng)然,<b>如果</b>用戶對(duì)于如何顯示數(shù)據(jù)無(wú)所謂的話,這也算不了什么大問(wèn)題。我之所以強(qiáng)調(diào)這個(gè)“如果”,是因?yàn)楸M管用戶有時(shí)在設(shè)計(jì)時(shí)并不要求能夠分頁(yè)、排序或編輯記錄,但這樣的要求往往會(huì)在開(kāi)發(fā)后期,或在他們能看到顯示出來(lái)的記錄后產(chǎn)生。
Repeater唯一優(yōu)于DataGrid和DataList的特點(diǎn)是它的性能,尤其明顯優(yōu)于DataGrid。而比DataList略高一點(diǎn)點(diǎn)。
[結(jié)論]
在ASP.Net頁(yè)面上顯示數(shù)據(jù)時(shí),多數(shù)的程序員會(huì)選擇他們所熟悉的控件來(lái)使用,特別是DataGrid。然而,這樣盲目的選擇在沒(méi)有“最好的通用控件”的情況下是不明智的。在選擇控件來(lái)顯示數(shù)據(jù)前,不妨問(wèn)自己幾個(gè)問(wèn)題來(lái)幫助決策:是否允許用戶對(duì)記錄排序?是不是記錄需要顯示在非表格的情況下?頁(yè)面是否會(huì)被高頻度地訪問(wèn),因此應(yīng)多考慮性能?
DataGrid提供了最多的功能,如允許訪問(wèn)者對(duì)記錄編輯、排序或分頁(yè)。同時(shí)它也是最容易使用的,甚至于簡(jiǎn)單到只需要將之添加到頁(yè)面中而不必額外編寫(xiě)代碼。不過(guò)這些易用性是以性能的損失為代價(jià)的。DataGrid在三種控件中是效率最低的,特別是在使用Web Form的情況下。
通過(guò)使用模板,DataList提供了比DataGrid更加優(yōu)秀的界面效果。不過(guò)這需要以犧牲一定的開(kāi)發(fā)時(shí)間為代價(jià)。為了添加排序、分頁(yè)和編輯功能,程序員不得不花費(fèi)比使用DataGrid更多的精力來(lái)進(jìn)行編碼,雖然它的性能要優(yōu)于DataGrid。
最后,Repeater允許對(duì)數(shù)據(jù)記錄作最大限度的HTML定制。通常,使用Repeater來(lái)顯示數(shù)據(jù)記錄比使用DataGrid和DataList要耗費(fèi)更長(zhǎng)的開(kāi)發(fā)時(shí)間。另外,它不支持內(nèi)建的編輯、排序和分頁(yè)功能。所幸的是,Repeater在性能上要優(yōu)于其它兩種控件,特別是明顯優(yōu)于DataGrid。
[附錄]
WAST測(cè)試設(shè)定
測(cè)試是在運(yùn)行Microsoft Windows 2003 Server操作系統(tǒng)的筆記本電腦上完成的。基本配置如下:Intel P4 2.4G CPU;512 MB RAM;30GB Ultra ATA Hard drive;網(wǎng)頁(yè)服務(wù)器使用IIS 6.0;ASP.Net版本為1.1。此測(cè)試中的WAST被設(shè)置成使用單線程,每個(gè)測(cè)試時(shí)間為一分鐘。
測(cè)試代碼http://download.microsoft.com/download/9/e/9/9e97b2f8-b317-4751-9ac1-2e34eebec26a/DataControlsPerfTest_Setup.msi點(diǎn)擊此處下載
總結(jié)
以上是生活随笔為你收集整理的关于何种情况下使用DataGrid、DataList或Repeater的一些讨论的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 单链表功能大全
- 下一篇: Repeater控件的分页问题