共用方式為


自訂 DataList 的編輯介面 (C#)

作者:Scott Mitchell

下載 PDF

在本教學課程中,我們將為 DataList 建立更豐富的編輯介面,其中包含 DropDownList 和 CheckBox。

簡介

DataList 中的 EditItemTemplate 標記和 Web 控制項會定義其可編輯的介面。 到目前為止,我們在所有可編輯的 DataList 範例中,可編輯的介面是由 TextBox Web 控制項所組成。 在 上述教學課程 中,我們會藉由新增驗證控件來改善編輯時間用戶體驗。

EditItemTemplate可以進一步擴充以包含 TextBox 以外的 Web 控件,例如 DropDownLists、RadioButtonLists、Calendars 等等。 如同 TextBox,自訂編輯介面以包含其他 Web 控件時,請採用下列步驟:

  1. 將 Web 控制項新增至 EditItemTemplate
  2. 使用數據系結語法,將對應的數據域值指派給適當的屬性。
  3. 在事件處理程式中 UpdateCommand ,以程式設計方式存取 Web 控件值,並將其傳遞至適當的 BLL 方法。

在本教學課程中,我們將為 DataList 建立更豐富的編輯介面,其中包含 DropDownList 和 CheckBox。 特別是,我們將建立一個 DataList 來列出產品資訊,並允許產品名稱、供應商、類別和已停止的狀態更新 (請參閱圖 1) 。

編輯介面包含 TextBox、兩個 DropDownList 和 CheckBox

圖 1:編輯介面包含 TextBox、兩個 DropDownList 和 CheckBox (按兩下即可檢視大小完整的影像)

步驟 1:顯示產品資訊

我們必須先建置只讀介面,才能建立DataList可編輯的介面。 從開啟CustomizedUI.aspx資料夾的頁面EditDeleteDataList開始,然後從 Designer,將 DataList 新增至頁面,並將其ID屬性設定為 Products。 從 DataList 的智慧標記中,建立新的 ObjectDataSource。 將這個新的 ObjectDataSource ProductsDataSource 命名為 ,並將其設定為從 ProductsBLL 類別 s GetProducts 方法擷取數據。 如同先前可編輯的 DataList 教學課程,我們將直接前往商業規則層來更新已編輯的產品資訊。 因此,將 UPDATE、INSERT 和 DELETE 索引標籤中的下拉式清單設定為 ([無]) 。

將 UPDATE、INSERT 和 DELETE 索引標籤 Drop-Down 清單 設定為 [無] ()

圖 2:將 UPDATE、INSERT 和 DELETE 索引標籤 Drop-Down 清單 設定為 ([無]) (按兩下即可檢視大小完整的映像)

設定 ObjectDataSource 之後,Visual Studio 會為 DataList 建立預設值 ItemTemplate ,其中列出每個傳回之數據欄位的名稱和值。 ItemTemplate修改 ,讓範本列出元素中的<h4>產品名稱,以及類別名稱、供應商名稱、價格和已停止的狀態。 此外,新增 [編輯] 按鈕,確定其 CommandName 屬性已設定為 [編輯]。 我的 ItemTemplate 宣告式標記如下:

<ItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="CategoryNameLabel" runat="server"
                    Text='<%# Eval("CategoryName") %>' />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="SupplierNameLabel" runat="server"
                    Text='<%# Eval("SupplierName") %>' />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="DiscontinuedLabel" runat="server"
                    Text='<%# Eval("Discontinued") %>' />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="EditButton"
                    Text="Edit" CommandName="Edit" />
            </td>
        </tr>
    </table>
    <br />
</ItemTemplate>

上述標記會使用 <產品名稱的 h4> 標題和其餘欄位的四欄 <table> 來配置產品資訊。 ProductPropertyLabel在中Styles.css定義的和 ProductPropertyValue CSS 類別已在先前的教學課程中討論過。 圖 3 顯示透過瀏覽器檢視時的進度。

顯示每個產品的名稱、供應商、類別、已停止狀態和價格

圖 3:[每個產品的名稱]、[供貨商]、[類別]、[已停止狀態] 和 [價格] 會顯示 (按兩下即可檢視大小完整的影像)

步驟 2:將 Web 控制項新增至編輯介面

建置自訂 DataList 編輯介面的第一個步驟是將所需的 Web 控制項新增至 EditItemTemplate。 特別是,我們需要DropDownList作為類別、另一個用於供應商,以及已停止狀態的 CheckBox。 由於產品價格在此範例中無法編輯,因此我們可以使用標籤 Web 控件繼續顯示它。

若要自定義編輯介面,請按兩下 DataList 智慧標記中的 [編輯範本] 連結,然後從下拉式清單中選擇 EditItemTemplate 選項。 將 DropDownList 新增至 , EditItemTemplate 並將其設定 IDCategories

新增類別的DropDownList

圖 4:針對 [類別] 新增 DropDownList (按兩下以檢視大小完整的影像)

接下來,從DropDownList的智慧標記中,選取 [選擇數據源] 選項,然後建立名為 CategoriesDataSource的新 ObjectDataSource。 將此 ObjectDataSource 設定為使用 CategoriesBLL 類別 s GetCategories() 方法, (請參閱圖 5) 。 接下來,DropDownList s 數據源組態精靈會提示數據欄位用於每個 ListItemTextValue 屬性。 讓DropDownList顯示 CategoryName 數據欄位,並使用 CategoryID 做為值,如圖 6 所示。

建立名為 CategoriesDataSource 的新 ObjectDataSource

圖 5:建立名為 CategoriesDataSource 的新 ObjectDataSource (按兩下即可檢視大小完整的映像)

設定DropDownList的顯示和值欄位

圖 6:設定 DropDownList 的 [顯示] 和 [值字段] (按兩下以檢視大小完整的影像)

重複這一系列的步驟,為供應商建立DropDownList。 ID將此 DropDownList 的 設定為 Suppliers ,並將其 ObjectDataSource SuppliersDataSource命名為 。

新增兩個DropDownLists之後,請新增已停止狀態的 CheckBox 和產品名稱的 TextBox。 分別將 ID CheckBox 和 TextBox 的 s 設定為 DiscontinuedProductName。 新增 RequiredFieldValidator,以確保使用者提供產品名稱的值。

最後,新增 [更新] 和 [取消] 按鈕。 請記住,對於這兩個按鈕,其 CommandName 屬性會分別設定為 [更新] 和 [取消]。

您可以隨意配置編輯介面。 我已選擇從只讀介面使用相同的四欄 <table> 配置,如下列宣告式語法和螢幕快照所示:

<EditItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Name:</td>
            <td colspan="3" class="ProductPropertyValue">
                <asp:TextBox runat="server" ID="ProductName" Width="90%" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
                    ControlToValidate="ProductName"
                    ErrorMessage="You must enter a name for the product."
                    runat="server">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Categories" runat="server"
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID" />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Suppliers" DataTextField="CompanyName"
                    DataSourceID="SuppliersDataSource"
                    DataValueField="SupplierID" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:CheckBox runat="server" id="Discontinued" />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
                    Text="Update" />
                 
                <asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
                    Text="Cancel" CausesValidation="False" />
            </td>
        </tr>
    </table>
    <br />
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
        TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
        TypeName="SuppliersBLL">
    </asp:ObjectDataSource>
</EditItemTemplate>

編輯介面就像 Read-Only 介面一樣配置

圖 7:編輯介面的配置方式就像 Read-Only 介面 (按兩下即可檢視完整大小的影像)

步驟 3:建立 EditCommand 和 CancelCommand 事件處理程式

目前, (中沒有數據系結語法 EditItemTemplate ,但 UnitPriceLabel從) 逐字複製的 ItemTemplate 除外。 我們會立即新增數據系結語法,但首先讓我們建立 DataList EditCommandCancelCommand 事件的事件處理程式。 回想一下,事件處理程式的責任 EditCommand 是轉譯已按下 [編輯] 按鈕之 DataList 專案的編輯介面,而 CancelCommand s 作業則是將 DataList 傳回其預先編輯狀態。

建立這兩個事件處理程式,並讓它們使用下列程式代碼:

protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property and rebind the data
    Products.EditItemIndex = e.Item.ItemIndex;
    Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Return to DataList to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

有了這兩個事件處理程式,按兩下 [編輯] 按鈕會顯示編輯介面,然後按兩下 [取消] 按鈕會將編輯的項目傳回其只讀模式。 圖 8 顯示 DataList,在 [編輯] 按鈕已針對 Chef Anton s一個[單選混合] 按兩下之後。 因為我們尚未將任何數據系結語法新增至編輯介面,所以 TextBox 是空白的、ProductNameDiscontinued未核取的 CheckBox,以及從 CategoriesSuppliers DropDownLists 選取的第一個專案。

顯示已新增 EditCommand 和 CancelCommand 事件處理程式並選取 [編輯] 按鈕之後,DataList EditItemTemplate 的螢幕快照。

圖 8:按兩下 [編輯] 按鈕會顯示編輯介面 (按鍵即可檢視大小完整的影像)

步驟 4:將 DataBinding 語法新增至編輯介面

若要讓編輯介面顯示目前的產品值,我們需要使用數據系結語法,將數據域值指派給適當的 Web 控制項值。 您可以移至 [編輯範本] 畫面,然後從 Web 控件智慧標記選取 [編輯 DataBindings] 連結,透過 Designer 套用數據系結語法。 或者,數據系結語法可以直接新增至宣告式標記。

ProductName 數據域值指派給 ProductName TextBox 的 Text 屬性、 CategoryIDSupplierID 數據域值給 CategoriesSuppliers DropDownLists SelectedValue 屬性,並將 Discontinued 數據域值指派給 Discontinued CheckBox s Checked 屬性。 進行這些變更之後,請透過 Designer 或直接透過宣告式標記,透過瀏覽器重新瀏覽頁面,然後按兩下 Chef Anton sAtivebo Mix 的 [編輯] 按鈕。 如圖 9 所示,數據系結語法已將目前的值新增至 TextBox、DropDownLists 和 CheckBox。

顯示 DataList EditItemTemplate 的螢幕快照,其中已新增 DataBinding 語法並已選取 [編輯] 按鈕。

圖 9:按兩下 [編輯] 按鈕會顯示編輯介面 (按兩下以檢視大小完整的影像)

步驟 5:儲存 UpdateCommand 事件處理程式中的用戶變更

當使用者編輯產品並按兩下 [更新] 按鈕時,就會發生回傳,並引發DataList事件 UpdateCommand 。 在事件處理程式中,我們需要從 中的 EditItemTemplate Web 控件讀取 值,並使用 BLL 介面來更新資料庫中的產品。 如先前教學課程中所見, ProductID 更新產品的 可透過 DataKeys 集合存取。 使用者輸入的欄位是透過 FindControl("controlID")以程式設計方式參考 Web 控件來存取,如下列程式代碼所示:

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Make sure the page is valid...
    if (!Page.IsValid)
        return;
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    DropDownList categories = (DropDownList)e.Item.FindControl("Categories");
    DropDownList suppliers = (DropDownList)e.Item.FindControl("Suppliers");
    CheckBox discontinued = (CheckBox)e.Item.FindControl("Discontinued");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    int categoryIDValue = Convert.ToInt32(categories.SelectedValue);
    int supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);
    bool discontinuedValue = discontinued.Checked;
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue,
                              discontinuedValue, productID);
    // Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

程式代碼一開始會諮詢 Page.IsValid 屬性,以確保頁面上的所有驗證控件都有效。 如果 Page.IsValidTrue,則會從DataKeys集合讀取編輯的產品ProductID值,並以程式設計方式參考 中的EditItemTemplate數據輸入 Web 控制件。 接下來,這些 Web 控制件的值會讀入變數,然後傳遞至適當的 UpdateProduct 多載。 更新數據之後,DataList 會傳回其預先編輯狀態。

注意

我省略 了處理 BLL 和 DAL-Level 例外 狀況教學課程中新增的例外狀況處理邏輯,以便讓程式代碼保持焦點,並將這個範例設為焦點。 練習中,完成本教學課程之後,新增這項功能。

步驟 6:處理 NULL CategoryID 和 SupplierID 值

Northwind 資料庫允許NULL數據表CategoryID和數據SupplierID行的值Products。 不過,我們的編輯介面目前無法容納 NULL 值。 如果我們嘗試編輯具有其 或 資料行值的產品NULL,我們會收到 ArgumentOutOfRangeException 類似錯誤訊息的 ,其錯誤訊息類似於:『Categories』 有 SelectedValue,因為它不存在於專案清單中。SupplierIDCategoryID此外,目前無法將產品類別或供應商值從非NULL值變更為NULL一個類別。

若要支援 NULL 類別和供應商 DropDownLists 的值,我們需要新增額外的 ListItem。 我選擇使用 (None) 做為此 的值ListItem,但您可以視需要將它變更為Text其他 (,例如空字串) 。 最後,請記得將DropDownLists AppendDataBoundItems 設定為 True;如果您忘記這麼做,系結至DropDownList 的類別和供貨商將會覆寫以靜態方式新增 ListItem的 。

進行這些變更之後,DataList s EditItemTemplate 中的DropDownLists標記看起來應該如下所示:

<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
    DataTextField="CategoryName" DataValueField="CategoryID" runat="server"
    SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
    DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
    SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>

注意

靜態 ListItem 可以透過 Designer 或直接透過宣告式語法新增至DropDownList。 新增DropDownList專案來代表資料庫 NULL 值時,請務必透過宣告式語法來新增 ListItem 。 如果您在 Designer 中使用 ListItem Collection 編輯器,產生的宣告式語法會在指派空白字串時完全省略Value設定,建立宣告式標記,例如: <asp:ListItem>(None)</asp:ListItem>。 雖然這看起來可能無害,但遺失 Value 會導致DropDownList在其位置使用 Text 屬性值。 這表示如果選取此選項 NULLListItem , (None) 的值將會嘗試指派給產品數據欄位 (CategoryIDSupplierID,在本教學課程中) ,這會導致例外狀況。 藉由明確設定 Value=""NULL 當選取 時 NULLListItem ,會將值指派給產品數據欄位。

請花點時間透過瀏覽器檢視我們的進度。 編輯產品時, Categories 請注意 和 Suppliers DropDownLists在DropDownList開頭都有 (None) 選項。

The Categories and Suppliers DropDownLists include a (None) Option

圖 10CategoriesSuppliers DropDownList 包含 [無 (]) 選項 (按兩下即可檢視完整大小的影像)

若要將 (None) 選項儲存為資料庫 NULL 值,我們必須返回 UpdateCommand 事件處理程式。 將 categoryIDValuesupplierIDValue 變數變更為可為 Null 的整數,並只指派 DropDownList Nothing s SelectedValue 不是空字串時以外的值:

int? categoryIDValue = null;
if (!string.IsNullOrEmpty(categories.SelectedValue))
    categoryIDValue = Convert.ToInt32(categories.SelectedValue);
int? supplierIDValue = null;
if (!string.IsNullOrEmpty(suppliers.SelectedValue))
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);

使用此變更時,如果使用者從任一下拉式清單中 (選取了 [無) ] 選項,則會將 的值 Nothing 傳入 UpdateProduct BLL 方法中,這兩個 NULL 清單對應至資料庫值。

摘要

在本教學課程中,我們已瞭解如何建立更複雜的 DataList 編輯介面,其中包含三個不同的輸入 Web 控件 TextBox、兩個 DropDownList 和 CheckBox 以及驗證控件。 建置編輯介面時,不論使用的 Web 控件為何,步驟都相同:一開始,請先將 Web 控件新增至 DataList s EditItemTemplate;使用數據系結語法來指派具有適當 Web 控件屬性的對應數據域值;在事件處理程式中 UpdateCommand ,以程式設計方式存取 Web 控件及其適當屬性, 將其值傳遞至 BLL。

建立編輯介面時,不論它是由 TextBox 或不同 Web 控件的集合所組成,請務必正確地處理資料庫 NULL 值。 考慮 NULL s 時,您不僅必須在編輯介面中正確顯示現有的 NULL 值,也提供將值標示為 NULL的方法。 對於 DataLists 中的 DropDownList,這通常表示將 屬性明確設定為空字串的靜態ListItemValue, () Value="" ,並將一些程式代碼新增至UpdateCommand事件處理程式,以判斷是否已NULL``ListItem選取 。

快樂的程序設計!

關於作者

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

特別感謝

本教學課程系列是由許多實用的檢閱者所檢閱。 本教學課程的首席檢閱者是 Dennis Patterson、David Suru 和 Randy Schmidt。 想要檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com。