在 GridView 的頁尾顯示摘要資訊 (C#)

作者:Scott Mitchell

下載 PDF

摘要資訊通常會顯示在摘要數據列的報表底部。 GridView 控件可以將頁尾數據列包含在其中,我們可以以程式設計方式插入匯總數據的單元格中。 在本教學課程中,我們將瞭解如何在此頁尾數據列中顯示匯總數據。

簡介

除了查看每個產品的價格、庫存單位、訂單單位和重新排序層級之外,使用者也可能對匯總資訊感興趣,例如平均值、庫存單位總數等等。 這類摘要資訊通常會顯示在摘要數據列的報表底部。 GridView 控件可以將頁尾數據列包含在其中,我們可以以程式設計方式插入匯總數據的單元格中。

這項工作提供我們三項挑戰:

  1. 設定 GridView 以顯示其頁尾數據列
  2. 判斷摘要數據;也就是說,我們要如何計算股票中單位的平均值或總單位?
  3. 將摘要數據插入頁尾數據列的適當儲存格

在本教學課程中,我們將瞭解如何克服這些挑戰。 具體而言,我們將建立頁面,以列出下拉式清單中的類別,其中已選取類別的產品顯示在 GridView 中。 GridView 會包含頁尾數據列,其中顯示庫存中單位的平均值和總單位數,以及該類別中產品的順序。

摘要信息會顯示在 GridView 的頁尾列中

圖 1:[摘要資訊] 會顯示在 GridView 的頁尾列 (按兩下以檢視大小完整的影像)

本教學課程是以產品主要/詳細數據介面的類別為基礎,以先前的主要 /詳細數據篩選搭配DropDownList 教學課程所涵蓋的概念為基礎。 如果您尚未完成先前的教學課程,請先這麼做,再繼續進行此教學課程。

步驟 1:新增類別 DropDownList 和 Products GridView

在自行將摘要資訊新增至 GridView 的頁尾之前,讓我們先建置主要/詳細數據報表。 完成此第一個步驟之後,我們將探討如何包含摘要數據。

首先, SummaryDataInFooter.aspx 開啟資料夾中的頁面 CustomFormatting 。 新增 DropDownList 控制項,並將其設定 IDCategories。 接下來,按兩下DropDownList智慧標記中的 [選擇資料源] 連結,並選擇加入名為 CategoriesDataSource 的新 ObjectDataSource,以叫用 CategoriesBLL 類別 GetCategories() 的 方法。

新增名為 CategoriesDataSource 的新 ObjectDataSource

圖 2:新增名為 CategoriesDataSource (Click 以檢視大小完整的影像)

讓 ObjectDataSource 叫用 CategoriesBLL 類別的 GetCategories () 方法

圖 3:讓 ObjectDataSource 叫 CategoriesBLL 用 類別 GetCategories() 的方法 (按兩下即可檢視大小完整的影像)

設定 ObjectDataSource 之後,精靈會將我們傳回 DropDownList 的數據源組態精靈,而我們需要指定應該顯示哪些數據域值,以及哪一個應該對應到 DropDownList 的值 ListItem 。 讓 CategoryName 欄位顯示,並使用 CategoryID 做為值。

分別使用 CategoryName 和 CategoryID 欄位做為 ListItems 的文字和值

圖 4:分別使用 CategoryNameCategoryID 字段作為 ValueListItemText 和 ,分別 (按兩下即可檢視大小完整的影像)

此時,我們有DropDownList () Categories 列出系統中的類別。 我們現在需要新增 GridView,以列出屬於所選類別的產品。 不過,在這麼做之前,請花點時間檢查DropDownList智慧標記中的 [啟用 AutoPostBack] 複選框。 如同使用 DropDownList進行主數據篩選 教學課程中所述,每次變更DropDownList值時,都會將DropDownList的 AutoPostBack 屬性 true 設定回傳回頁面。 這會導致 GridView 重新整理,顯示新選取類別的產品。 AutoPostBack如果屬性設定為 false (預設) ,變更類別不會造成回傳,因此不會更新列出的產品。

核取DropDownList智慧標記中的 [啟用 AutoPostBack] 複選框

圖 5:在DropDownList的智慧標記中核取 [啟用 AutoPostBack] 複選框, (按兩下即可檢視大小完整的映像)

將 GridView 控件新增至頁面,以顯示所選類別的產品。 將 GridView 的 ID 設定為 ProductsInCategory ,並將其系結至名為 ProductsInCategoryDataSource的新 ObjectDataSource。

新增名為 ProductsInCategoryDataSource 的新 ObjectDataSource

圖 6:新增名為 ProductsInCategoryDataSource (Click 以檢視大小完整的映射)

設定 ObjectDataSource,以便叫用 ProductsBLL 類別的 GetProductsByCategoryID(categoryID) 方法。

讓 ObjectDataSource 叫用 GetProductsByCategoryID (categoryID) 方法

圖 7:讓 ObjectDataSource 叫用 GetProductsByCategoryID(categoryID) 方法 (按兩下即可檢視大小完整的映射)

GetProductsByCategoryID(categoryID)由於 方法採用輸入參數,因此在精靈的最後一個步驟中,我們可以指定參數值的來源。 若要從選取的類別顯示這些產品,請從 Categories DropDownList提取參數。

顯示 [設定數據源] 視窗的螢幕快照,其中已選取 categoryID 參數值。

圖 8categoryID 從 [選取類別] 下拉式清單取得 [參數值] (按兩下即可檢視完整大小的影像)

完成精靈之後,GridView 會針對每個產品屬性都有 BoundField。 讓我們清除這些 BoundField,以便只ProductName顯示 、 UnitPriceUnitsInStockUnitsOnOrder 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>

此時,我們有一份完整運作的主要/詳細數據報表,顯示屬於所選類別的產品名稱、單價、庫存單位和單位。

此螢幕快照顯示屬於[訂用帳戶] 類別之產品的 GridView 報表。

圖 9categoryID 從 [選取的類別] 下拉式清單取得參數值 (按兩下即可檢視大小完整的影像)

GridView 控件可以同時顯示頁首和頁尾數據列。 根據和 屬性的值ShowHeader,分別顯示這些數據列,預設trueShowHeader為 和 ShowFooterfalseShowFooter 若要在 GridView 中包含頁尾,只要將其 ShowFooter 屬性設定為 true

將 GridView 的 ShowFooter 屬性設定為 true

圖 10:將 GridView 的 ShowFooter 屬性設定為 true (按兩下即可檢視大小完整的影像)

頁尾數據列具有 GridView 中定義之每個欄位的儲存格;不過,根據預設,這些儲存格是空的。 花點時間在瀏覽器中檢視我們的進度。 現在, ShowFooter 當 屬性設定為 true時,GridView 會包含空的頁尾數據列。

GridView 現在包含頁尾數據列

圖 11:GridView 現在包含頁尾數據列, (按兩下即可檢視大小完整的影像)

圖 11 中的頁尾數據列沒有顯示,因為它具有白色背景。 讓我們在 中Styles.css建立一個 FooterStyle CSS 類別,以指定深紅色背景,然後在 GridView.skin Theme 中DataWebControls設定 [面板] 檔案,以將此 CSS 類別指派給 GridView 的 FooterStyleCssClass 屬性。 如果您需要對面板和主題進行筆刷,請參閱 使用 ObjectDataSource 顯示數據 教學課程。

首先,將下列 CSS 類別新增至 Styles.css

.FooterStyle
{
    background-color: #a33;
    color: White;
    text-align: right;
}

FooterStyle CSS 類別的樣式HeaderStyle與 類別類似,雖然 HeaderStyle的背景色彩較深,而且其文字會以粗體字型顯示。 此外,頁尾中的文字靠右對齊,而頁首的文字會置中。

接下來,若要將此 CSS 類別與每個 GridView 的頁尾建立關聯,請在 Theme 中DataWebControls開啟 GridView.skin 檔案,並設定 FooterStyleCssClass 屬性。 新增之後,檔案的標記看起來應該像這樣:

<asp:GridView runat="server" CssClass="DataWebControlStyle">
   <AlternatingRowStyle CssClass="AlternatingRowStyle" />
   <RowStyle CssClass="RowStyle" />
   <HeaderStyle CssClass="HeaderStyle" />
   <FooterStyle CssClass="FooterStyle" />
   <SelectedRowStyle CssClass="SelectedRowStyle" />
</asp:GridView>

如以下螢幕快照所示,這項變更可讓頁尾更清楚地顯示。

此螢幕快照顯示 GridView 頁尾數據列中以新背景色彩格式化的摘要數據。

圖 12:GridView 的頁尾數據列現在具有紅色背景色彩, (按兩下即可檢視大小完整的影像)

步驟 3:計算摘要數據

隨著 GridView 的頁尾顯示,我們所面臨的下一個挑戰是如何計算摘要數據。 有兩種方式可計算此匯總資訊:

  1. 透過 SQL 查詢,我們可以對資料庫發出額外的查詢,以計算特定類別的摘要數據。 SQL 包含數個聚合函數以及 子 GROUP BY 句,以指定要摘要數據的數據。 下列 SQL 查詢會傳回所需的資訊:

    SELECT CategoryID, AVG(UnitPrice), SUM(UnitsInStock),
    SUM(UnitsOnOrder)
    FROM Products
    WHERE CategoryID = categoryID
    GROUP BY CategoryID
    

    當然,您不想直接從SummaryDataInFooter.aspx頁面發出此查詢,而是在 和 ProductsBLLProductsTableAdapter建立 方法。

  2. 計算這項資訊,因為其新增至 GridView,如 自定義格式化式數據 教學課程中所述,GridView 的 RowDataBound 事件處理程式會在數據系結之後,針對每個新增至 GridView 的數據列引發一次。 藉由為此事件建立事件處理程式,我們可以保留我們想要匯總的值總計。 最後一個數據列系結至 GridView 之後,我們有計算平均值所需的總計和資訊。

我通常會採用第二種方法,因為它可節省資料庫行程,以及實作數據存取層和商業規則層中摘要功能所需的工作,但任一種方法都足夠。 在本教學課程中,讓我們使用第二個選項,並使用事件處理程式來追蹤執行總計 RowDataBound

RowDataBound在 Designer 中選取 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 中總計和非記錄的數目NULLUnitPrice ,因為平均值是這兩個數位的商數。

加總摘要數據后,最後一個步驟是將其顯示在 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") 如何讓平均價格摘要資訊格式化成貨幣。

此螢幕快照顯示 GridView 頁尾數據列中格式化為貨幣的摘要數據。

圖 13:GridView 的頁尾數據列現在具有紅色背景色彩, (按兩下即可檢視大小完整的影像)

摘要

顯示摘要數據是常見的報表需求,GridView 控件可讓您輕鬆地在其頁尾數據列中包含這類資訊。 當 GridView 的 ShowFooter 屬性設定 true 為 ,而且可以透過 RowDataBound 事件處理程式以程式設計方式設定儲存格中的文字時,就會顯示頁尾數據列。 計算摘要數據可藉由重新查詢資料庫,或使用 ASP.NET 頁面程序代碼後置類別中的程式代碼來完成,以程式設計方式計算摘要數據。

本教學課程將探討使用 GridView、DetailsView 和 FormView 控件的自定義格式設定。 下一個教學課程會開始探索如何使用這些相同的控件來插入、更新和刪除數據。

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET