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+ 頁面框架和服務器控件,以及說明作為此框架一部分的控件的對象模型的參考書目。
|