datagrid 控件
datagrid 控件使您可以生成數據源格式豐富的列表表示。此外,它還支持隨其它操作選擇項目。
本節的四個示例使用包含有關書名信息(標題、標題id、作者、價格和出版日期)的表。全部數據都用titlesdb.xml 中的xml 予以維持。在建立頁面來表示此表的內容並選擇書籍時,這些示例遵循增量方法。代碼列表包含黑體文本,以表明一個示例構建於以前示例時所作的更改。
截自titlesdb.xml:
<root>
<schema id=documentelement targetnamespace=
xmlns=http://www.w3.org/1999/xmlschema
xmlns:msdata=urn:schemas-microsoft-com:xml-msdata>
<element name=title>
<complextype content=elementonly>
<element name=title_id type=string></element>
<element name=title type=string></element>
<element name=au_name type=string></element>
<element name=price msdata:datatype=system.currency
minoccurs=0
type=string></element>
<element name=pubdate type=timeinstant></element>
</complextype>
<unique name=titleconstraint msdata:primarykey=true>
<selector>.</selector>
<field>title_id</field>
</unique>
</element>
</schema>
<documentelement>
<title>
<title_id>bu1032</title_id>
<title>the busy executive's database guide</title>
<au_name>marjorie green</au_name>
<price>19.99</price>
<pubdate>1991-06-12t07:00:00</pubdate>
</title>
...
</documentelement>
</root>
在典型的web 應用程序中,為了獲得最大的可伸縮性和性能上的好處,很可能會使用web 服務或商業對象來存取數據。為了簡化這些示例並將注意力集中在使用datagrid 而不是數據存取上,我們選擇在應用程序啟動時一次性加載數據,並在global.asax 中的asp 應用程序狀態中高速緩存所得的dataset,如下所示。
截自global.asax:
public void application_onstart() {
filestream fs = null;
dataset ds = null;
try {
fs = new filestream(server.mappath(titlesdb.xml), filemode.open,
fileaccess.read);
ds = new dataset();
// 將xml 文件中的數據加載到dataset 中
ds.readxml(fs);
} finally {
if (fs != null) {
fs.close();
fs = null;
}
}
// 將數據集高速緩存到應用程序狀態中,以便在單個頁面中使用
application[titlesdataset] = ds;
}
datagrid1
datagrid1 說明datagrid 的基本用法,說明控件如何用最少的用戶代碼生成表示來提供豐富的功能。
圖4. 通過使用具有自動生成列的datagrid 產生的示例
截自datagrid1.aspx:
<%@ page language=c# src=datagrid.cs inherits=samples.datagridpage%>
...
<asp:datagrid runat=server id=titlesgrid>
</asp:datagrid>
上面的.aspx 文件顯示在不設置datagrid 控件任何屬性的情況下對其進行聲明。
datagrid.cs:
namespace samples {
...
public class datagridpage : page {
protected datagrid titlesgrid;
public icollection gettitleslist() {
// 從在應用程序狀態中高速緩存的dataset 中檢索標題列表。
dataset titlesdataset = (dataset)application[titlesdataset];
if (titlesdataset != null) {
return titlesdataset.tables[title].defaultview;
}
else {
return null;
}
}
private void loadtitlesgrid() {
// 從數據庫中檢索數據
icollection titleslist = gettitleslist();
// 設置控件的數據源
titlesgrid.datasource = titleslist;
// 並使它用此數據源構建其項目
titlesgrid.databind();
}
protected override void onload(eventargs e) {
base.onload(e);
if (!ispostback) {
// 首次請求此頁
loadtitlesgrid();
}
}
}
}
.cs 文件包含用於此頁的代碼。此代碼與datalist1 示例中使用的代碼功能相同。在對此頁的首次請求中,它覆蓋onload 方法以檢索數據並在調用databind 之前設置控件的datasource 屬性。這將使datagrid 創建其項目,這些項目是表中必要的行。在回傳處理的過程中,datagrid 從狀態(該狀態包括在上一次請求中所保存的單元格內容)重新創建項目。
此示例說明了datagrid 控件的autogeneratecolumns 屬性的功能。此屬性的默認值為true。當設置為true 時,datagrid 將使用reflection 檢查其數據源和對象,並為每個公用屬性或字段創建一個列。在此示例中,控件表示“標題”表中當前的所有字段。這一功能允許用最少的用戶代碼快速而容易地生成任何數據源的列表表示。
每個自動生成列的類型都是boundcolumn。這種列類型將與其關聯的屬性值轉換為要用作窗體元格文本的字符串。
datagrid2
datagrid2 說明具有在.aspx 文件中定義的columns 集合的datagrid。
圖5. 通過使用具有指定列的datagrid 產生的示例
摘自datagrid2.aspx:
<%@ page language=c# src=datagrid.cs inherits=samples.datagridpage%>
...
<asp:datagrid runat=server id=titlesgrid
autogeneratecolumns=false>
<property name=columns>
<asp:boundcolumn headertext=title datafield=title/>
<asp:boundcolumn headertext=author datafield=au_name/>
<asp:boundcolumn headertext=date published datafield=pubdate/>
<asp:boundcolumn headertext=price datafield=price/>
</property>
</asp:datagrid>
此.aspx 文件顯示了一個具有用戶指定的列集合的datagrid 控件。此示例使用與datagrid1 相同的有代碼支持的文件,因為不需要更改任何代碼。
datagrid 的autogeneratecolumns 屬性被設置為假,從而阻止控件自動生成列,而讓用戶負責定義將要在表中表示的列。
有許多好處:
您可控制列的順序。以聲明的順序表示列。另一方面,自動生成的列是按用映像檢索到的順序表示的,此順序不必與代碼中的列順序或數據庫表本身的列順序相匹配。
可以用列的headertext 屬性來指定每列的標頭。在前一個示例中,列標頭指明了字段名,這可能並不合適。當在此模式下使用控件時,columns 還提供其它可設置的屬性。
自動生成的列的類型始終是boundcolumn。指定列集合使用戶可以控制每列的類型。
datagrid3
datagrid3 通過添加可視格式化和內容格式化構建於datagrid2 之上。
圖6. 由設置了樣式和格式化屬性的datagrid 產生的示例
摘自datagrid3.aspx:
<%@ page language=c# src=datagrid.cs inherits=samples.datagridpage%>
...
<asp:datagrid runat=server id=titlesgrid
autogeneratecolumns=false
width=80%
backcolor=white
borderwidth=1px borderstyle=solid cellpadding=2 cellspacing=0
bordercolor=tan
font-name=宋體font-size=8pt>
<property name=columns>
<asp:boundcolumn headertext=title datafield=title/>
<asp:boundcolumn headertext=author datafield=au_name/>
<asp:boundcolumn headertext=date published datafield=pubdate
dataformatstring={0:mmm yyyy}/>
<asp:boundcolumn headertext=price datafield=price
dataformatstring={0:c}>
<property name=itemstyle>
<asp:tableitemstyle horizontalalign=right/>
</property>
</asp:boundcolumn>
</property>
<property name=headerstyle>
<asp:tableitemstyle backcolor=darkred forecolor=white
font-bold=true/>
</property>
<property name=itemstyle>
<asp:tableitemstyle forecolor=darkslateblue/>
</property>
<property name=alternatingitemstyle>
<asp:tableitemstyle backcolor=beige/>
</property>
</asp:datagrid>
此.aspx 文件顯示了與前面相同的datagrid 控件聲明,並設置了各種樣式屬性。這將導致視覺上更具吸引力的表示。仍就不需要對代碼進行任何更改,使用與以前示例相同的有代碼支持的文件。
因為它是從webcontrol 得到的,所以datagrid 控件繼承了諸如width、backcolor、borderstyle 和font.name 之類的樣式屬性。此外,datagrid 提供諸如cellpadding 這樣的屬性,這些屬性是特定於表的。這些屬性允許從總體上定制控件。
聲明還顯示了設置的若干項目樣式,如headerstyle 和alternatingitemstyle。這些樣式控制著它們相應項目的外觀。請注意此示例中出現的樣式合併。備選項目與一般項目的前景色相同,因為它們的樣式是alternatingitemstyle 和itemstyle 的組合。最後,此示例還通過右對齊價格列中的文本說明了為特定列設置樣式。
datagrid 還允許您格式化其單元格中的文本內容。這是通過設置boundcolumn 的dataformatstring 屬性值完成的。該列使用其格式說明格式化使用string.format 的單元格內容。此屬性可隨格式化類型(如日期或貨幣)一起預置或附加任意內容。此外,由於格式化考慮了當前頁的cultureinfo 和請求,所以它也支持全局化。如果未指定格式,則使用該值的tostring 方法。
datagrid4
datagrid4 說明如何通過處理selectedindexchanged 事件來利用datagrid 中的選擇。
圖7. 由允許選擇其包含項目的datagrid 產生的示例
截自datagrid4.aspx:
<%@ page language=c# src=datagrid4.cs inherits=samples.datagrid4page%>
...
<asp:datagrid runat=server id=titlesgrid
autogeneratecolumns=false
width=80%
backcolor=white
borderwidth=1px borderstyle=solid cellpadding=2 cellspacing=0
bordercolor=tan
font-name=宋體font-size=8pt
datakeyfield=title_id
onselectedindexchanged=onselectedindexchangedtitlesgrid>
<property name=columns>
<asp:buttoncolumn text=select command=select/>
<asp:boundcolumn headertext=title datafield=title/>
<asp:boundcolumn headertext=author datafield=au_name/>
<asp:boundcolumn headertext=date published datafield=pubdate
dataformatstring={0:mmm yyyy}/>
<asp:boundcolumn headertext=price datafield=price
dataformatstring={0:c}>
<property name=itemstyle>
<asp:tableitemstyle horizontalalign=right/>
</property>
</asp:boundcolumn>
</property>
<property name=headerstyle>
<asp:tableitemstyle backcolor=darkred forecolor=white
font-bold=true/>
</property>
<property name=itemstyle>
<asp:tableitemstyle forecolor=darkslateblue/>
</property>
<property name=alternatingitemstyle>
<asp:tableitemstyle backcolor=beige/>
</property>
<property name=selecteditemstyle>
<asp:tableitemstyle backcolor=palegoldenrod font-bold=true/>
</property>
</asp:datagrid>
...
<asp:label runat=server id=selectioninfolabel font-name=宋體font-size=8pt/>
在此.aspx 文件中,為datagrid 的selectedindexchanged 事件註冊了一個事件處理程序。此事件處理程序是在有代碼支持的文件中實現的。已在列集合中添加了一個命令為“select”的buttoncolumn,使得datagrid 為每個項目表示一個包含select 按鈕的附加列。同時指定了selecteditemstyle。此樣式用於從視覺上區分選定的項目。最後還指定了datagrid 的datakeyfield 屬性。此字段將置入datagrid 的datakeys 集合,該集合將在有代碼支持的文件中用到。
datagrid4.cs:
namespace samples {
...
public class datagrid4page : page {
protected datagrid titlesgrid;
protected label selectioninfolabel;
public icollection gettitleslist() {
// 從在應用程序狀態中高速緩存的dataset 中檢索標題列表。
dataset titlesdataset = (dataset)application[titlesdataset];
if (titlesdataset != null) {
return titlesdataset.tables[title].defaultview;
}
else {
return null;
}
}
private void loadtitlesgrid() {
// 從數據庫中檢索數據
icollection titleslist = gettitleslist();
// 設置控件的數據源並重新設置其選擇,
titlesgrid.datasource = titleslist;
titlesgrid.selectedindex = -1;
// 並使該控件使用此數據源構建其項目
titlesgrid.databind();
// 更新選定的標題信息
updateselectedtitleinfo();
}
protected override void onload(eventargs e) {
base.onload(e);
if (!ispostback) {
// 首次請求此頁
loadtitlesgrid();
}
}
// 處理datagrid 的onselectedindexchanged 事件
protected void onselectedindexchangedtitlesgrid(object sender,
eventargs e) {
updateselectedtitleinfo();
}
private void updateselectedtitleinfo() {
// 獲取選定的索引
int selindex = titlesgrid.selectedindex;
string seltitleid = null;
string selectioninfo;
if (selindex != -1) {
// 顯示選定標題的關鍵字段
seltitleid = (string)titlesgrid.datakeys[selindex];
selectioninfo = id of selected title: + seltitleid;
}
else {
selectioninfo = no title is currently selected.;
}
selectioninfolabel.text = selectioninfo;
}
}
}
此.cs 文件包含處理selectedindexchanged 事件以及在datagrid 下顯示選定標題的id 的邏輯。 datagrid 處理命令事件,該事件是通過包含在其項目中的按鈕觸發的。它識別標準命令“select”,該命令使其更改它的selectedindex 屬性,並通過觸發此事件來將此更改通知用戶的代碼。
在實現事件處理程序的過程中,示例代碼調用updateselectedtitleinfo 方法。該方法負責顯示有關選定書名的信息,本例中為標題的id。在更現實的方案中,此id 可用來鏈接某個頁面,以顯示有關選定標題的更多詳細信息。
id 是通過訪問datakeys 集合進行檢索的。該集合是因為設置了datakeyfield 屬性而置入的。通常,將它設置為主關鍵字或使用戶可以唯一標識項目的某些其它字段,並將此信息用作後續的數據庫查詢或過濾數據中的準則。
此示例說明除了僅僅表示數據源中的對象之外,如何進一步支持諸如選擇數據源中對象之類的操作。 datagrid 包含對若干其它特性(如排序、分頁、現場編輯和templatecolumns)的支持。但是,這些特定特性超出了本文的討論範圍,將在以後的文章中加以探討。
repeater、datalist 或datagrid?
repeater、datalist 和datagrid 控件共享公用編程模型。同時,每個控件都被設計為側重某個特定方案,為正確的方案選擇正確的列表綁定控件是一個重要的決策。本節說明控件層次結構和每種控件的功能,以及每種控件可能用於的典型方案的示例。
正如在下面的類層次結構中看到的那樣,repeater 是一種小巧輕便的控件。它只繼承了基本control類的功能,如id 屬性和子控件集合。另一方面,datalist 控件和datagrid 控件都繼承了webcontrol 功能,如樣式和外觀屬性。
圖8. 列表綁定控件的類層次結構
在對像模型方面,repeater 控件是最簡單的控件。它同時也是最小的數據綁定控件並且基本上是不同的,即它不會強制使用任何特殊的ui 佈局。最後的表示遵循生成文本的方法,其方式是通過重複為此控件指定的模板內容。此控件對樣式和外觀屬性或行為不提供任何內建的支持。對於需要完全控製表示的方案而言,它是一個極好的選擇。
datalist 控件是強制使用分列佈局或流佈局的repeater。它繼承了webcontrol 中實現的外觀屬性,並增加了適用於它所創建的項目的其它樣式屬性。 datalist 控件還包括對其項目標準操作(如選擇、編輯和刪除)的支持。它很適用於生成分佈於一列或多列的水平或垂直的項目序列流。
datagrid 控件強制使用列或行的列表佈局。與datalist 類似,此控件提供樣式和外觀屬性。除選擇和編輯之外,datagrid 還支持對整個項目集合的高級操作,如分頁和排序。 datagrid 和datalist 的一個主要區別是datagrid 不包含任何模板屬性,即datagrid 控件的項目或行是非模板化的。但是,將templatecolumn 添加到datagrid 中就可以在特定列中使用模板。
下表是列表綁定控件所提供的功能的摘要。
功能repeater datalist datagrid
模板是(必需) 是(必需) 列內(可選)
列表佈局否否是
流佈局是是否
分列/報紙欄目樣式佈局否是否
樣式和外觀屬性否是是
選擇否是是
編輯否是是
刪除否是是
分頁否否是
排序否否是
相關資源
隨microsoft .net framework sdk 發布的quickstart 示例包含這些控件的若干示例,以及說明使用xml 和web 服務存取數據的示例。 sdk 附帶的文檔包括相關主題的概念性資料,如asp+ 頁面框架和服務器控件,以及說明作為此框架一部分的控件的對像模型的參考書目。