程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> ASP.NET基礎 >> 在ASP.NET 2.0中操作數據之四十:自定義DataList編輯界面

在ASP.NET 2.0中操作數據之四十:自定義DataList編輯界面

編輯:ASP.NET基礎

導言

  DataList的編輯界面由EditItemTemplate裡的標記語言和web控件定義。在目前為止所做的DataList編輯功能的例子裡,編輯界面都只包含TextBox。在前面一章裡,我們通過添加驗證控件來增加了用戶體驗,提高了可用性。

  EditItemTemplate可以包含除了TextBox以外的很多控件,比如DropDownList, RadioButtonList, Calendar等。和使用TextBox一樣,使用這些控件自定義編輯界面時,步驟如下:

為EditItemTemplate添加控件.
使用綁定語法將相關的字段值賦給控件的屬性.
在UpdateCommand事件處理裡, 編程訪問web控件的值,並將它傳給相關的BLL的方法.

  本章我們將為DataList創建一個更豐富的編輯界面,它將包含DropDownList和CheckBox。我們將創建一個列出product信息的DataList,用戶可以更新它的name,supplier,category和discontinued status。見圖1。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463572.png
圖 1: 編輯界面包含一個TextBox, 兩個 DropDownLists和一個CheckBox

第一步: 顯示Product 信息

  在創建DataList的編輯界面前,我們需要先創建一個只讀界面。先打開EditDeleteDataList文件夾下的CustomizedUI.aspx頁,拖一個DataList進來,將ID設為Products。通過DataList的智能標簽,創建一個名為ProductsDataSource的ObjectDataSource,用ProductsBLL類的GetProducts方法配置它。象前面一章一樣,我們將直接通過BLL來更新product信息。在UPDATE,INSERT,DELETE標簽裡選擇None.

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463620.png
圖 2: 在UPDATE, INSERT, DELETE 標簽的下拉列表裡選擇 (None)

  配置完ObjectDataSource後,Visual Studio會自動創建默認的ItemTemplate,列出每個字段的值。將product name用<h4>表示,並添加一個Edit button,確保將它的CommandName屬性設為 “Edit”. 我的標記語言如下:

<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>表示product name,4列的<table>展示其它字段。前面已經討論過Styles.css裡定義的ProductPropertyLabel和productPropertyValue類。浏覽該頁,見圖3。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463648.png
圖 3: 顯示product信息

第二步: 為編輯界面添加web控件

  首先向EditItemTemplate裡添加需要的web控件。我們需要用一個DropDownList表示category,一個DropDownList表示supplier,一個CheckBox 表示discontinued state。由於本例中不用編輯price,所以仍然用Label來表示它。

  點擊DataList的智能標簽上的“Edit Templates”,選擇EditItemTemplate,為它添加一個ID為Categories的EditItemTemplate。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463686.png
圖 4: 為Categories添加一個DropDownList

  然後從DropDownList的智能標簽裡選擇“Choose Data Source”,創建一個名為CategoriesDataSource的ObjectDataSource。用CategoriesBLL類的GetCategories()方法配制它(見圖5)。數據源配置向導會要求為ListItem Text和Value選擇字段。讓DropDownList 顯示CategoryName,CategoryID作為Value,見圖6。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463880.png
圖 5: 創建 ObjectDataSource

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463893.png
圖 6: 配置DropDownList的 Display 字段和Value 字段

  重復上面的步驟,為suppliers創建一個ID為Suppliers的DropDownList 和一個名為SuppliersDataSource的ObjectDataSource。

  然後為discontinued state 添加一個CheckBox ,為name添加一個TextBox 。將他們的ID分別設為Discontinued和ProductName。為product name添加一個RequiredFieldValidator 確保用戶必須提供這個值。

  最後添加Update 和Cancel button。記得這兩個button的CommandName屬性必須分別設為“Update” 和“Cancel”。你可以將編輯界面以你喜歡的方式展示。我選擇使用和只讀界面一樣的界面來顯示,見下面的聲明代碼和截圖。

<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>

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463806.png
圖 7: 編輯界面和只讀界面的展示差不多

第三步: 創建 EditCommand和CancelCommand Event Handlers

  現在在EditItemTemplate裡除了UnitPriceLabel外還沒有綁定語法(從ItemTemplate復制過來的代碼)。在添加綁定語法前我們首先為DataList的EditCommand和CancelCommand創建事件處理。EditCommand事件處理的目標是為了將Edit button被點擊的item展示為編輯狀態,而CancelCommand的目標是將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();
}
  

  完成這些後,點擊Edit button會進入編輯界面,點擊Cancel button會返回只讀模式。見圖8。由於現在還沒有為編輯界面添加綁定語法,TextBox是空白的,CheckBox 未被選中,兩個DropDownList裡都是第一個item被選中。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463920.png
圖 8: 點擊Edit Button顯示編輯界面

第四步: 為編輯界面增加綁定語法

  為了讓編輯界面顯示當前product的值,我們需要使用綁定語法將字段的值賦給web控件。綁定語法可以通過選擇web控件的智能標簽的“Edit DataBindings”或者直接添加聲明語法來實現。

  將ProductName字段的值賦給ProductName TextBox的Text屬性,CategoryID和SupplierID字段賦給Categories和Suppliers DropDownList的SelectedValue屬性,Discontinued字段賦給Discontinued CheckBox的Checked屬性。完成這些後,浏覽頁面並點擊Edit button.見圖9。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463918.png
圖 9: 點擊Edit Button 顯示編輯界面

第五步: 在UpdateCommand Event Handler保存用戶的更改

  當用戶編輯product並點Update button後,會postback並激發UpdateCommand事件。在事件處理裡,我們需要從EditItemTemplate裡讀出web控件的值,並和BLL交互,然後更新數據庫裡的product。如我們在前面一章看到的那樣,被更新的product的ProductID可以通過DataKeys集合來獲取。用戶輸入的值可以通過FindControl("controlID")來編程獲取,見下面的代碼:

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.IsValid為True,從DataKeys集合裡讀出被編輯的product 的ProductID的值,並引用EditItemTemplate裡的web控件。然後將這些控件的值讀到變量裡,並傳給UpdateProduct方法。完成更新後,DataList會返回到編輯前的狀態。

  注意:我省略了某章異常處理,目的是為了使本章的代碼看起來目的性更強。你可以在完成本章後自己添加異常處理的功能作為練習。

第六步: 處理空的CategoryID 和SupplierID 值

  Northwind 數據庫允許Products表裡的CategoryID和SupplierID列為空。然而我們的編輯界面目前還沒有提供可選空值。如果我們試圖編輯一個無論是CategoryID還是SupplierID為空的product,將會產生ArgumentOutOfRangeException異常。目前我們也沒有將product的category或supplier的值從一個非空值轉換為空值的方法。

  為了在DropDownLists裡添加空值,我們需要添加一個ListItem。我將ListItem裡的Text顯示為"(None)",你可以將它賦為任何你希望的值(比如空字符串)。最後,記得將DropDownLists的AppendDataBoundItems設為True。如果你沒有這麼做,綁定到DropDownList 的categories 和suppliers 會被添加的ListItem覆蓋。完成這些後,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>

  注意:為DropDownList 添加ListItems可以通過設計器或者聲明語法來完成。當添加一個表示數據庫空值的item時,要確保是通過聲明語法來完成的。如果你使用設計器的ListItem集合編輯器,當賦空字符串時,產生的聲明語法會忽略Value的設置,產生想<asp:ListItem>(None)</asp:ListItem>這樣的語句。這個看起來並沒有什麼關系,但是缺少Value會讓DropDownList 使用Text屬性的值作為Value。這意味著當NULL  ListItem被選擇時,“(None)” 會被賦給product的CategoryID或SupplierID字段,這會引起異常。而顯式的將Value設為“”,當NULL  ListItem被選擇時一個空值會被賦給product的CategoryID或SupplierID字段。現在浏覽該頁。當編輯product時,注意Categories和Suppliers DropDownLists 開頭都包含一個“(None)”選項。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916463918.png
圖 10: Categories 和Suppliers DropDownLists包含 “(None)”

  為了將“(None)” 保存為數據庫NULL值,我們需要回到UpdateCommand事件處理。將categoryIDValue和supplierIDValue變量設為可為空的整型,並在DropDownList的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);

  完成這個後,如果用戶在DropDownList裡選擇“(None)” 時,一個空值將被傳給UpdateProduct BLL方法,它相當於數據庫的NULL值。

總結

  本章我們學習了如何為DataList創建一個更復雜的編輯界面,它包含三種不同的web控件— 一個TextBox,兩個DropDownLists和一個CheckBox —並且包含驗證控件。當創建編輯界面時,不管使用什麼控件,步驟都是一樣的:先為EditItemTemplate添加控件;將字段值通過綁定語法賦給對應的web控件的屬性;在UpdateCommand事件處理中編程訪問web控件和它們的屬性,並將值傳給BLL。

  當創建編輯界面時,無論它僅僅是由TextBox組成還是由不同的web控件組成,要確保正確的處理數據庫NULL值。當處理NULL時,不僅需要在編輯界面正確顯示已經存在的NULL值,還需要提供輸入NULL值的方法。對DataLists裡的DropDownLists 來說,這通常意味著需要添加一個Value屬性被顯式設為空字符串(Value="")的ListItem,然後在UpdateCommand事件處理裡判斷NULL ListItem是否被選中。

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數據教程》,希望對大家的學習ASP.NET有所幫助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved