根據資料格式化 DataList 和重複項 (C#)
在本教學課程中,我們將逐步解說如何格式化 DataList 和 Repeater 控件的外觀範例,方法是使用範本內的格式化函式或處理 DataBound 事件。
簡介
如上一個教學課程中所見,DataList 提供一些會影響其外觀的樣式相關屬性。 特別是,我們已瞭解如何將預設 CSS 類別指派給 DataList s HeaderStyle
、 ItemStyle
、 AlternatingItemStyle
和 SelectedItemStyle
屬性。 除了這四個屬性之外,DataList 還包含一些其他樣式相關屬性,例如 Font
、 ForeColor
、 BackColor
和 BorderWidth
,以命名為一些。 Repeater 控制件不包含任何樣式相關的屬性。 任何這類樣式設定都必須直接在重複項範本中的標記內進行。
不過,數據的格式通常取決於數據本身。 例如,當列出產品時,如果產品已停止,我們可能會想要以淺灰色字型色彩顯示產品資訊,或者如果值為零,我們可能會想要反 UnitsInStock
白顯示該值。 如先前教學課程中所見,GridView、DetailsView 和 FormView 提供兩種不同的方式,根據數據格式化其外觀:
- 事件
DataBound
會針對適當的DataBound
事件建立事件處理程式,此事件處理程式會在數據系結至 GridViewRowDataBound
的每個專案 (之後引發;如果是 DataList 和 Repeater,則為ItemDataBound
事件) 。 在該事件處理程式中,您可以檢查資料並設定設定格式決策。 我們已在 自定義格式化根據數據 教學課程中檢查這項技術。 - 在 DetailsView 或 GridView 控件中使用 TemplateFields 或 FormView 控件中的範本時,我們可以將格式化函式新增至 ASP.NET 頁面程式代碼後置類別、商業規則層,或可從 Web 應用程式存取的任何其他類別庫。 此格式設定函式可以接受任意數目的輸入參數,但必須傳回 HTML 才能在範本中呈現。 第一次在 GridView 控制項中使用 TemplateFields 教學課程中檢查格式化函式。
這兩種格式化技術都可搭配 DataList 和 Repeater 控件使用。 在本教學課程中,我們將逐步解說這兩種控件使用兩種技巧的範例。
ItemDataBound
使用事件處理程式
當數據系結至 DataList 時,請從數據源控件,或透過以程式設計方式將數據指派給控件 s DataSource
屬性,並呼叫其 DataBind()
方法時,DataList s DataBinding
事件會引發、列舉數據源,以及每個數據記錄都會系結至 DataList。 針對數據源中的每個記錄,DataList 會 DataListItem
建立對象,然後系結至目前的記錄。 在此程式中,DataList 會引發兩個事件:
ItemCreated
建立 之後DataListItem
引發ItemDataBound
在目前記錄系結至 之後引發DataListItem
下列步驟概述 DataList 控件的數據系結程式。
DataList 事件
DataBinding
會引發數據系結至 DataList
針對數據源中的每個記錄
- 建立
DataListItem
物件 ItemCreated
引發事件- 將記錄系結至
DataListItem
ItemDataBound
引發事件DataListItem
將加入至Items
集合
- 建立
將數據系結至 Repeater 控制項時,它會逐步執行完全相同的步驟序列。 唯一的差別在於,重複程式會使用 RepeaterItem
,而不是DataListItem
建立的實例。
注意
astute 讀取器可能會注意到DataList和Repeater系結至數據時,與 GridView 系結至數據時,步驟序列之間的稍微異常。 在數據系結程序的結尾,GridView 會引發 DataBound
事件;不過,DataList 或 Repeater 控件都沒有這類事件。 這是因為 DataList 和 Repeater 控制件是在 ASP.NET 1.x 時間範圍中建立的,在前置和後置事件處理程式模式變得常見之前。
如同 GridView,根據數據格式化的其中一個選項是建立事件的事件處理程式 ItemDataBound
。 此事件處理程式會檢查剛系結至 DataListItem
或 RepeaterItem
的數據,並視需要影響控件的格式。
針對 DataList 控件,可以使用樣式相關的屬性來實DataListItem
作整個專案的格式化變更,其中包括標準 Font
、ForeColor
、、 BackColor
CssClass
等等。 為了影響 DataList 範本內特定 Web 控件的格式設定,我們需要以程式設計方式存取和修改這些 Web 控制項的樣式。 我們已瞭解如何在 以數據為基礎的自定義格式 設定教學課程中完成此作業。 如同 Repeater 控制項,類別 RepeaterItem
沒有與樣式相關的屬性;因此,在事件處理程式中所做的 RepeaterItem
所有樣式相關變更都必須透過以程式設計方式存取及更新範本內的 ItemDataBound
Web 控制項來完成。
ItemDataBound
由於 DataList 和 Repeater 的格式設定技術幾乎完全相同,因此我們的範例將著重於使用 DataList。
步驟 1:在 DataList 中顯示產品資訊
在擔心格式設定之前,讓我們先建立使用 DataList 來顯示產品資訊的頁面。 在上一個 教學課程 中,我們建立了一個 DataList,其中 ItemTemplate
顯示每個產品名稱、類別、供應商、每個單位的數量,以及價格。 讓我們在此教學課程中重複這項功能。 若要達成此目的,您可以從頭開始重新建立DataList及其 ObjectDataSource,或從上一個教學課程中建立的頁面複製這些控件, Basics.aspx
() ,並將其貼到本教學課程的頁面 (Formatting.aspx
) 。
將 DataList 和 ObjectDataSource 功能從 Basics.aspx
複寫到 Formatting.aspx
之後,請花點時間將 DataList 的 ID
屬性從 DataList1
變更為更具描述性的 ItemDataBoundFormattingExample
。 接下來,在瀏覽器中檢視 DataList。 如圖 1 所示,每個產品之間的唯一格式差異是背景色彩替代。
圖 1:產品列在 DataList 控件中, (按兩下即可檢視完整大小的影像)
在本教學課程中,讓我們格式化 DataList,讓任何價格小於 $20.00 的產品都會以黃色醒目提示其名稱和單價。
步驟 2:以程式設計方式判斷 ItemDataBound 事件處理程式中的數據值
由於只有價格低於 $20.00 的產品才會套用自定義格式,因此我們必須能夠判斷每個產品的價格。 將數據系結至 DataList 時,DataList 會列舉其數據源中的記錄,並針對每個記錄建立 DataListItem
實例,將數據源記錄系結至 DataListItem
。 將特定記錄的數據系結至目前 DataListItem
對象之後,就會引發DataList s ItemDataBound
事件。 我們可以為此事件建立事件處理程式,以檢查目前 DataListItem
的數據值,並根據這些值,進行任何必要的格式變更。
建立 ItemDataBound
DataList 的事件,並新增下列程式代碼:
protected void ItemDataBoundFormattingExample_ItemDataBound
(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Programmatically reference the ProductsRow instance bound
// to this DataListItem
Northwind.ProductsRow product =
(Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
// See if the UnitPrice is not NULL and less than $20.00
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
{
// TODO: Highlight the product's name and price
}
}
}
雖然 DataList ItemDataBound
事件處理程式背後的概念和語意與 GridView RowDataBound
事件處理程式在 自定義格式依據數據 教學課程中使用的概念和語意相同,語法會稍有不同。 ItemDataBound
當事件引發時,DataListItem
只會透過 e.Item
(傳遞至數據的對應事件處理程式,而不是 e.Row
,如同 GridView 的RowDataBound
事件處理程式) 一樣。 DataList 的 ItemDataBound
事件處理程式會針對新增至 DataList 的每個 數據列引發,包括頁首數據列、頁尾數據列和分隔符數據列。 不過,產品資訊只會系結至數據列。 因此,使用 ItemDataBound
事件來檢查系結至 DataList 的數據時,我們必須先確定我們使用數據項。 這可以藉由檢查 DataListItem
s ItemType
屬性來完成,這可以有 下列八個值之一:
AlternatingItem
EditItem
Footer
Header
Item
Pager
SelectedItem
Separator
Item
和 AlternatingItem``DataListItem
都會讓 DataList 的數據項產生。 假設我們使用 Item
或 AlternatingItem
,我們會存取系結至目前 DataListItem
的實際ProductsRow
實例。 DataListItem
s DataItem
屬性包含 對象的DataRowView
參考,其 Row
屬性會提供實際ProductsRow
對象的參考。
接下來,我們會檢查 ProductsRow
實例的 UnitPrice
屬性。 由於 Products 資料表字段 UnitPrice
允許 NULL
值,因此在嘗試存取 UnitPrice
屬性之前,我們必須先檢查它 NULL
是否有使用 IsUnitPriceNull()
方法的值。 UnitPrice
如果值不是 NULL
,我們會檢查其是否小於 $20.00。 如果它確實低於 $20.00,則我們需要套用自定義格式設定。
步驟 3:醒目提示產品名稱和價格
一旦我們知道產品的價格小於 $20.00,所有仍會強調其名稱和價格。 若要達成此目的,我們必須先以程式設計方式參考 中顯示產品名稱和價格的標籤 ItemTemplate
控制件。 接下來,我們必須讓它們顯示黃色背景。 您可以直接修改標籤 BackColor
屬性 (LabelID.BackColor = Color.Yellow
) 來套用此格式設定資訊;在理想情況下,所有顯示相關的事項都應該透過串聯樣式表單來表示。 事實上,我們已經有一個樣式表單,提供 中定義的所需格式,該格式設定是在 自定義格式根據數據教學課程中Styles.css
- AffordablePriceEmphasis
建立和討論。
若要套用格式設定,只要將兩個 Label Web 控件 CssClass
屬性設定為 AffordablePriceEmphasis
,如下列程式代碼所示:
// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
UnitPriceLabel.CssClass = "AffordablePriceEmphasis";
完成事件處理程序之後 ItemDataBound
,請重新瀏覽 Formatting.aspx
瀏覽器中的頁面。 如圖 2 所示,價格低於 $20.00 的產品會同時醒目提示其名稱和價格。
圖 2:[ 點選] 以檢視大小完整的影像) 醒目 (提示小於 $20.00 的產品
注意
由於 DataList 會轉譯為 HTML <table>
,因此其 DataListItem
實例具有樣式相關的屬性,可設定為將特定樣式套用至整個專案。 例如,如果我們想要在價格小於 $20.00 時反白顯示 整個 專案黃色,我們可以取代參考標籤的程式代碼,並使用下列程式代碼行來設定其 CssClass
屬性: e.Item.CssClass = "AffordablePriceEmphasis"
(請參閱圖 3) 。
RepeaterItem
但是,組成 Repeater 控件的 ,不提供這類樣式層級的屬性。 因此,將自定義格式套用至 Repeater 需要將樣式屬性套用至重複項範本內的 Web 控制件,就像我們在圖 2 中所做的一樣。
圖 3:針對 $20.00 (按兩下以檢視大小完整影像 的產品,已醒目提示整個產品專案)
從範本內使用格式化函式
在 GridView 控件中使用 TemplateFields 教學課程中,我們已瞭解如何使用 GridView TemplateField 內的格式化函式,根據系結至 GridView 數據列的數據套用自定義格式設定。 格式化函式是從範本叫用的方法,並傳回要在其位置發出的 HTML。 格式化函式可以位於 ASP.NET 頁的程式代碼後置類別中,也可以集中到資料夾或個別類別庫專案中的類別檔案 App_Code
中。 如果您打算在多個 ASP.NET 頁面或其他 ASP.NET Web 應用程式中使用相同的格式設定函式,將格式設定函式移出 ASP.NET 頁的程式代碼後置類別是理想的方式。
為了示範格式設定函式,假設產品名稱已停止,請讓產品資訊包含產品名稱旁的 [DISCONTINUED] 文字。 此外,如果價格小於 $20.00 (,讓我們將價格醒目提示為黃色,如同我們在 ItemDataBound
事件處理程式範例中) 一樣;如果價格是 $20.00 或更高版本,讓我們不要顯示實際價格,而是文字,請呼叫價位報價。 圖 4 顯示已套用這些格式規則的產品清單螢幕快照。
圖 4:針對昂貴產品,價格會以文字取代,請呼叫價位報價 (按兩下以檢視大小完整的影像)
步驟 1:建立格式化函式
在此範例中,我們需要兩個格式化函式,其中一個會顯示產品名稱以及文字 [DISCONTINUED],如有需要,另一個則會在小於 $20.00 的情況下顯示反白顯示的價格,或文字,否則請呼叫價位引號。 讓我們在 ASP.NET 頁的程式代碼後置類別中建立這些函式,並將其命名為 DisplayProductNameAndDiscontinuedStatus
和 DisplayPrice
。 這兩種方法都需要傳回 HTML 來轉譯為字串,而且兩者都必須標示 Protected
為 (或 Public
) ,才能從 ASP.NET 頁面的宣告式語法部分叫用。 這兩種方法的程序代碼如下:
protected string DisplayProductNameAndDiscontinuedStatus
(string productName, bool discontinued)
{
// Return just the productName if discontinued is false
if (!discontinued)
return productName;
else
// otherwise, return the productName appended with the text "[DISCONTINUED]"
return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
// If price is less than $20.00, return the price, highlighted
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
return string.Concat("<span class=\"AffordablePriceEmphasis\">",
product.UnitPrice.ToString("C"), "</span>");
else
// Otherwise return the text, "Please call for a price quote"
return "<span>Please call for a price quote</span>";
}
請注意,方法DisplayProductNameAndDiscontinuedStatus
接受 和 discontinued
數據欄位的值productName
做為純量值,而 DisplayPrice
方法接受ProductsRow
實例 (,而不是unitPrice
純量值) 。 任一種方法都能夠運作;不過,如果格式化函式使用可包含資料庫NULL
值的純量值 (,例如 UnitPrice
;或ProductName
Discontinued
不允許NULL
值) ,則必須特別小心處理這些純量輸入。
特別是,輸入參數的類型必須為 , Object
因為傳入值可能是 DBNull
實例,而不是預期的數據類型。 此外,必須進行檢查,以判斷傳入值是否為資料庫 NULL
值。 也就是說,如果我們想要 DisplayPrice
方法接受價格做為純量值,就必須使用下列程序代碼:
protected string DisplayPrice(object unitPrice)
{
// If price is less than $20.00, return the price, highlighted
if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
return string.Concat("<span class=\"AffordablePriceEmphasis\">",
((decimal) unitPrice).ToString("C"), "</span>");
else
// Otherwise return the text, "Please call for a price quote"
return "<span>Please call for a price quote</span>";
}
請注意, unitPrice
輸入參數的類型為 Object
,而且已修改條件語句以確定是否 unitPrice
為 DBNull
。 此外,由於 unitPrice
輸入參數是以 傳入 Object
,因此必須轉換成十進位值。
步驟 2:從 DataList s ItemTemplate 呼叫格式化函式
將格式化函式新增至我們的 ASP.NET 頁程序代碼後置類別時,所有保留專案都是從 DataList s 叫用 ItemTemplate
這些格式化函式。 若要從範本呼叫格式化函式,請將函式呼叫放在數據系結語法中:
<%# MethodName(inputParameter1, inputParameter2, ...) %>
在 DataList 中 ItemTemplate
, ProductNameLabel
標籤 Web 控制項目前會指派其 Text
屬性 <%# Eval("ProductName") %>
來顯示產品名稱。 若要讓它顯示名稱加上文字 [DISCONTINUED],如有需要,請更新宣告式語法,使其改為指派 Text
方法的值 DisplayProductNameAndDiscontinuedStatus
。 這麼做時,我們必須使用 Eval("columnName")
語法傳入產品名稱和已停止的值。 Eval
會傳回 型別的值,但DisplayProductNameAndDiscontinuedStatus
方法需要 類型的Object
String
輸入參數和 Boolean
;因此,我們必須將 Eval
方法傳回的值轉換成預期的輸入參數類型,如下所示:
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
(bool) Eval("Discontinued")) %>'>
</asp:Label>
</h4>
為了顯示價格,我們可以直接將 Label s Text
屬性設定UnitPriceLabel
為 方法所DisplayPrice
傳回的值,就像我們在顯示產品名稱和 [DISCONTINUED] 文字時所做的一樣。 不過,我們改為傳入整個ProductsRow
實例,而不是以純量輸入參數的形式傳入 UnitPrice
:
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# DisplayPrice((Northwind.ProductsRow)
((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>
有了對格式化函式的呼叫,請花點時間在瀏覽器中檢視我們的進度。 您的畫面看起來應該與圖 5 類似,其中已停止的產品包括文字 [DISCONTINUED],而那些產品的成本超過 $20.00 美元,且其價格已取代為文字,請撥打價位引號 。
圖 5:針對昂貴的產品,價格會以文字取代,請在 單擊以檢視全尺寸影像 (呼叫價位,以檢視大小完整的影像)
摘要
您可以使用兩種技術,根據數據格式化 DataList 或 Repeater 控件的內容。 第一個技巧是建立 ItemDataBound
事件的事件處理程式,這會在數據源中的每個記錄系結至新的 DataListItem
或 RepeaterItem
時引發。 在 ItemDataBound
事件處理程式中,可以檢查目前的項目數據,然後將格式設定套用至範本的內容,或針對 DataListItem
s 套用至整個專案本身。
或者,自定義格式設定可透過格式化函式實現。 格式化函式是從 DataList 或 Repeater 範本叫用的方法,可傳回 HTML 以在其位置發出。 通常,格式化函式所傳回的 HTML 是由系結至目前專案的值所決定。 這些值可以傳遞至格式化函式,可以是純量值,或是傳入系結至專案的完整物件 (,例如 ProductsRow
實例) 。
快樂的程序設計!
關於作者
Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 自 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET。
特別感謝
本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Yaakov Ellis、Randy Schmidt 和 Liz Shulok。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。