在 GridView 的頁尾顯示摘要資訊 (C#)
由斯科特· 米切爾
摘要資訊通常會顯示在摘要數據列的報表底部。 GridView 控制件可以包含頁尾數據列,我們可以以程式設計方式插入匯總數據的數據格。 在本教學課程中,我們將瞭解如何在此頁尾數據列中顯示匯總數據。
簡介
除了查看每個產品的價格、庫存單位、訂單單位和重新排序層級之外,使用者可能還對匯總資訊感興趣,例如平均價格、庫存單位總數等等。 這類摘要資訊通常會顯示在摘要數據列中報表底部。 GridView 控制件可以包含頁尾數據列,我們可以以程式設計方式插入匯總數據的數據格。
這項工作提供我們三項挑戰:
- 設定 GridView 以顯示其頁尾數據列
- 判斷摘要數據;也就是說,我們如何計算股票中單位的平均價格或總單位?
- 將摘要數據插入頁尾數據列的適當儲存格
在本教學課程中,我們將瞭解如何克服這些挑戰。 具體來說,我們將建立一個頁面,其中列出下拉式清單中的類別,其中已選取類別的產品顯示在 GridView 中。 GridView 會包含頁尾數據列,其中顯示庫存中單位的平均價格和總單位數,以及該類別中產品的訂單。
圖 1:摘要資訊會顯示在 GridView 的頁尾數據列中(按兩下以檢視完整大小的影像)
本教學課程以產品主要/詳細數據介面類別為基礎,以先前 主要/詳細數據篩選搭配DropDownList 教學課程中涵蓋的概念為基礎。 如果您尚未完成先前的教學課程,請先這麼做,再繼續進行此教學課程。
步驟 1:新增 Categories DropDownList 和 Products GridView
在將摘要資訊新增至 GridView 頁尾之前,讓我們先建置主要/詳細數據報表。 完成第一個步驟之後,我們將探討如何包含摘要數據。
從開啟 SummaryDataInFooter.aspx
資料夾中的頁面 CustomFormatting
開始。 新增 DropDownList 控制項,並將其設定 ID
為 Categories
。 接下來,按兩下DropDownList智慧標記中的 [選擇資料源] 連結,並選擇加入名為 CategoriesDataSource
的新 ObjectDataSource,以叫 CategoriesBLL
用 類別的 GetCategories()
方法。
圖 2:新增名為 CategoriesDataSource
的 ObjectDataSource (按兩下以檢視完整大小的影像)
圖 3:讓 ObjectDataSource 叫 CategoriesBLL
用類別的 GetCategories()
方法 (按兩下以檢視完整大小的影像)
設定 ObjectDataSource 之後,精靈會將我們傳回 DropDownList 的數據源組態精靈,從中指定要顯示哪些數據域值,以及哪一個應該對應至 DropDownList 的值 ListItem
。 顯示欄位, CategoryName
並使用 CategoryID
作為值。
圖 4:分別使用 CategoryName
和 CategoryID
字段作為 Text
和 Value
ListItem
,分別使用 (按兩下以檢視完整大小的影像)
此時,我們有一個DropDownList (Categories
) 列出系統中的類別。 我們現在需要新增 GridView,以列出屬於所選類別的產品。 不過,在我們這麼做之前,請花點時間檢查DropDownList智慧標記中的[啟用 AutoPostBack] 複選框。 如 Master/Detail Filtering With a DropDownList 教學課程中所述 ,將 DropDownList 的 AutoPostBack
屬性設定為 true
頁面,會在每次變更 DropDownList 值時回傳。 這會導致 GridView 重新整理,顯示新選取類別的產品。 AutoPostBack
如果 屬性設定為 false
(預設值),則變更類別不會造成回傳,因此不會更新列出的產品。
圖 5:核取 DropDownList 智慧標記中的 [啟用 AutoPostBack] 複選框 (按兩下以檢視完整大小的影像)
將 GridView 控件新增至頁面,以顯示所選類別的產品。 將 GridView 的 ID
設定為 ProductsInCategory
,並將它系結至名為 ProductsInCategoryDataSource
的新 ObjectDataSource。
圖 6:新增名為 ProductsInCategoryDataSource
的 ObjectDataSource (按兩下以檢視完整大小的影像)
設定 ObjectDataSource,讓它叫用 ProductsBLL
類別的 GetProductsByCategoryID(categoryID)
方法。
圖 7:讓 ObjectDataSource 叫 GetProductsByCategoryID(categoryID)
用 方法(按兩下以檢視完整大小的影像)
GetProductsByCategoryID(categoryID)
由於方法會採用輸入參數,因此在精靈的最後一個步驟中,我們可以指定參數值的來源。 若要從選取的類別顯示這些產品,請從 Categories
DropDownList提取參數。
圖 8:從選取的類別下拉式清單取得 categoryID
參數值 (按兩下以檢視完整大小的影像)
完成精靈之後,GridView 會針對每個產品屬性擁有 BoundField。 讓我們清除這些 BoundField,只ProductName
顯示 、 UnitPrice
UnitsInStock
和 UnitsOnOrder
BoundFields。 您可以隨意將任何欄位層級設定新增至剩餘的 BoundFields(例如將 格式化 UnitPrice
為貨幣)。 進行這些變更之後,GridView 的宣告式標記看起來應該如下所示:
<asp:GridView ID="ProductsInCategory" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsInCategoryDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="UnitsInStock"
HeaderText="Units In Stock" SortExpression="UnitsInStock">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="Units On Order" SortExpression="UnitsOnOrder">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
</Columns>
</asp:GridView>
此時,我們有一份功能完整的主要/詳細數據報告,其中顯示屬於所選類別的產品名稱、單價、庫存單位,以及依序排列的單位。
圖 9:從選取的類別下拉式清單取得 categoryID
參數值(按兩下以檢視完整大小的影像)
步驟 2:在 GridView 中顯示頁尾
GridView 控件可以同時顯示頁首和頁尾數據列。 這些資料欄會根據 和屬性的值ShowHeader
,分別顯示,預設值true
ShowHeader
為 和false
ShowFooter
ShowFooter
若要在 GridView 中包含頁尾,只需將其 ShowFooter
屬性設定為 true
。
圖 10:將 GridView 的 ShowFooter
屬性設定為 true
(按兩下以檢視完整大小的影像)
頁尾數據列具有 GridView 中定義之每個欄位的儲存格;不過,這些儲存格預設為空白。 花點時間在瀏覽器中檢視我們的進度。 當 屬性 ShowFooter
現在設定為 true
時,GridView 會包含空白頁尾數據列。
圖 11:GridView 現在包含頁尾數據列(按兩下以檢視完整大小的影像)
圖 11 中的頁尾數據列不會脫穎而出,因為它有白色背景。 讓我們在 中Styles.css
建立 FooterStyle
CSS 類別,以指定深紅色背景,然後在 Theme 中DataWebControls
設定 GridView.skin
Skin 檔案,將此 CSS 類別指派給 GridView 的 FooterStyle
CssClass
屬性。 如果您需要對面板和主題進行筆刷,請參閱 使用 ObjectDataSource 顯示數據教學課程 。
首先,將下列 CSS 類別新增至 Styles.css
:
.FooterStyle
{
background-color: #a33;
color: White;
text-align: right;
}
FooterStyle
CSS 類別在樣式上與 HeaderStyle
類別類似,雖然 HeaderStyle
的背景色彩較暗,而且其文字會以粗體字型顯示。 此外,頁尾中的文字會靠右對齊,而頁首的文字會置中。
接下來,若要將此 CSS 類別與每個 GridView 的頁尾產生關聯,請在 Theme 中DataWebControls
開啟GridView.skin
檔案,並設定 FooterStyle
的 CssClass
屬性。 新增之後,檔案的標記看起來應該像這樣:
<asp:GridView runat="server" CssClass="DataWebControlStyle">
<AlternatingRowStyle CssClass="AlternatingRowStyle" />
<RowStyle CssClass="RowStyle" />
<HeaderStyle CssClass="HeaderStyle" />
<FooterStyle CssClass="FooterStyle" />
<SelectedRowStyle CssClass="SelectedRowStyle" />
</asp:GridView>
如下面的螢幕快照所示,這項變更會讓頁尾更清楚地脫穎而出。
圖 12:GridView 的頁尾數據列現在有紅色的背景色彩(按兩下以檢視完整大小的影像)
步驟 3:計算摘要數據
隨著 GridView 頁尾的顯示,我們面臨的下一個挑戰就是如何計算摘要數據。 有兩種方式可計算此匯總資訊:
透過 SQL 查詢,我們可以對資料庫發出額外的查詢,以計算特定類別的摘要數據。 SQL 包含數個聚合函數以及
GROUP BY
子句,以指定要摘要數據的數據。 下列 SQL 查詢會帶回所需的資訊:SELECT CategoryID, AVG(UnitPrice), SUM(UnitsInStock), SUM(UnitsOnOrder) FROM Products WHERE CategoryID = categoryID GROUP BY CategoryID
當然,您不想直接從
SummaryDataInFooter.aspx
頁面發出此查詢,而是在 和ProductsBLL
中ProductsTableAdapter
建立 方法。計算這項資訊,因為它正在新增至 GridView,如自定義格式化式數據教學課程中所討論,GridView 的
RowDataBound
事件處理程式會在數據系結之後針對每個新增至 GridView 的數據列引發一次。 藉由為此事件建立事件處理程式,我們可以保留我們想要匯總的值總計。 在最後一個數據列系結至 GridView 之後,我們有計算平均值所需的總計和資訊。
我通常會採用第二種方法,因為它會儲存資料庫的行程,以及實作數據存取層和商業規則層中摘要功能所需的工作,但任一種方法都已足夠。 在本教學課程中,我們將使用第二個選項,並使用事件處理程式來追蹤執行總計 RowDataBound
。
RowDataBound
選取設計工具中的 GridView、按兩下 屬性視窗的閃電圖示,然後按兩下RowDataBound
事件,以建立 GridView 的事件處理程式。 這會在頁面的程式代碼後置類別中SummaryDataInFooter.aspx
建立名為 ProductsInCategory_RowDataBound
的新事件處理程式。
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
}
為了維持執行總計,我們需要在事件處理程式範圍之外定義變數。 建立下列四個頁面層級變數:
_totalUnitPrice
型別為 的 。decimal
_totalNonNullUnitPriceCount
型別為 的 。int
_totalUnitsInStock
型別為 的 。int
_totalUnitsOnOrder
型別為 的 。int
接下來,撰寫程式代碼,針對事件處理程式中 RowDataBound
遇到的每個數據列遞增這三個變數。
// Class-scope, running total variables...
decimal _totalUnitPrice = 0m;
int _totalNonNullUnitPriceCount = 0;
int _totalUnitsInStock = 0;
int _totalUnitsOnOrder = 0;
protected void ProductsInCategory_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Reference the ProductsRow via the e.Row.DataItem property
Northwind.ProductsRow product =
(Northwind.ProductsRow)
((System.Data.DataRowView)e.Row.DataItem).Row;
// Increment the running totals (if they are not NULL!)
if (!product.IsUnitPriceNull())
{
_totalUnitPrice += product.UnitPrice;
_totalNonNullUnitPriceCount++;
}
if (!product.IsUnitsInStockNull())
_totalUnitsInStock += product.UnitsInStock;
if (!product.IsUnitsOnOrderNull())
_totalUnitsOnOrder += product.UnitsOnOrder;
}
}
RowDataBound
事件處理程式一開始會確保我們正在處理 DataRow。 建立之後, Northwind.ProductsRow
剛系結至 GridViewRow
中的 e.Row
對象實例會儲存在變數 product
中。 接下來,執行的總變數會依目前產品的對應值遞增(假設它們不包含資料庫 NULL
值)。 我們會追蹤執行UnitPrice
總數和非記錄的數目NULL
UnitPrice
,因為平均價格是這兩個數位的商數。
步驟 4:在頁尾中顯示摘要數據
加總摘要數據后,最後一個步驟是在 GridView 的頁尾數據列中顯示。 這項工作也可以透過 RowDataBound
事件處理程式以程序設計方式完成。 回想一下, RowDataBound
事件處理程式會針對 系結至 GridView 的每個 數據列引發,包括頁尾數據列。 因此,我們可以使用下列程式代碼來增強事件處理程式,以在頁尾數據列中顯示數據:
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
... Increment the running totals ...
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
... Display the summary data in the footer ...
}
}
由於在加入所有數據列之後,頁尾數據列會新增至 GridView,因此我們可以確信,在準備在頁尾中顯示摘要數據時,執行中總計算將會完成。 然後,最後一個步驟是在頁尾的單元格中設定這些值。
若要在特定頁尾單元格中顯示文字,請使用 e.Row.Cells[index].Text = value
,其中 Cells
索引編製從 0 開始。 下列程式代碼會計算平均價格(總價格除以產品數目),並在 GridView 的適當頁尾數據格中依序顯示其庫存單位和單位總數。
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
... <i>Increment the running totals</i> ...
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
// Determine the average UnitPrice
decimal avgUnitPrice = _totalUnitPrice / (decimal) _totalNonNullUnitPriceCount;
// Display the summary data in the appropriate cells
e.Row.Cells[1].Text = "Avg.: " + avgUnitPrice.ToString("c");
e.Row.Cells[2].Text = "Total: " + _totalUnitsInStock.ToString();
e.Row.Cells[3].Text = "Total: " + _totalUnitsOnOrder.ToString();
}
}
圖 13 顯示新增此程式代碼之後的報表。 請注意, ToString("c")
如何讓平均價格摘要資訊格式化為貨幣。
圖 13:GridView 的頁尾數據列現在有紅色背景色彩(按兩下以檢視完整大小的影像)
摘要
顯示摘要數據是常見的報表需求,GridView 控件可讓您輕鬆地在其頁尾數據列中包含這類資訊。 當 GridView 的 ShowFooter
屬性設定為 true
,而且可以透過 RowDataBound
事件處理程式以程式設計方式設定儲存格中的文字時,就會顯示頁尾數據列。 計算摘要數據可以透過重新查詢資料庫,或使用 ASP.NET 頁面程序代碼後置類別中的程式代碼,以程式設計方式計算摘要數據來完成。
本教學課程最後會使用 GridView、DetailsView 和 FormView 控件來檢查自定義格式設定。 下一個教學課程會開始探索如何使用這些相同的控件插入、更新和刪除數據。
快樂的程序設計!
關於作者
斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET。