導言
當使用 GridView 、 DetailsView 或 FormView 控件的內建插入、編輯或刪除特征時,在用戶添加一條新記錄或更新 / 刪除一條現在記錄的過程中發生了多個步驟。正如我們之前一節里所討論的,在 GridView 中編輯一行時,保存( Update )和取消( Cancel )按鈕將取代編輯( Edit )按鈕,并且綁定列轉換成 TextBox 。在用戶更新了數據并點擊保存按鈕之后,下述步驟在回傳時執行:
1. 該 GridView 控件根據當前編輯行的唯一標識字段(通過 DataKeyNames 屬性)組裝它的 ObjectDataSource 的 UpdateParameters 參數,連同用戶輸入的值
2. 該 GridView 控件調用它的 ObjectDataSource 的 Update() 方法,它轉而調用潛在對象的適當的方法( ProductsDAL.UpdateProduct ,我們之前一節里)
3. 現在,這些隱含的數據,包含保存后的更改,被重新綁定到 GridView 控件
在這一連串的步驟里,觸發了許多事件,這讓我們可以創建事件處理程序從而在需要的地方增加自定義邏輯。例如,在第 1 步之前,觸發 GridView 的事件。在這里,如果有什么 validation 錯誤我們可以取消更新請求。當調用 Update() 方法時,觸發 ObjectDataSource 的 Updating 事件,提供了增加或自定義 UpdateParameters 的值的機會。在 ObjectDataSource 的潛在對象的方法完全執行后,觸發 ObjectDataSource 的 Updated 事件。針對 Updated 事件的事件處理程序可以檢查更新操作的相關詳細信息,例如影響了多少行數據,或者是否引發了一個異常。最后,在第 2 步之后, GridView 的 RowUpdated 事件觸發;針對此事件的事件處理程序可以檢查關于剛剛完成的更新操作的相關額外信息。
圖 1 描述了使用 GridView 更新時這一系列連續的事件和步驟。圖 1 里的這個事件模式不僅是在 GridView 的更新操作。從 GridView 、 DetailsView 或者 FormView 里插入、更新或者刪除數據時,數據 Web 服務器控件和 ObjectDataSource 都會發生這一連串的 pre-level 和 post-level 的事件。
圖
1:
當在
GridView
里更新數據時,觸發一連串的
Pre-
和
Post-
事件
在這一節里,我們將探討使用這些事件從而擴展 ASP.NET 數據 Web 服務器控件的內建插入、更新和刪除功能。我們也會看看如何自定義編輯界面從而僅僅更新部分產品字段。
第一步 : 更新產品的 ProductName 和 UnitPrice 字段
在之前一節的編輯界面里,包含了產品的所有字段并且它們都不是只讀的。如果我們從 GridView 中剔除一列( QuantityPerUnit ),那么當更新時數據 Web 服務器控件就不會設置 ObjectDataSource 的 QuantityPerUnit UpdateParameters 的值。 ObjectDataSource 則傳入一個 null 值到 UpdateProduct 這個業務邏輯層的方法,它將當前編輯的數據庫記錄的 QuantityPerUnit 字段更改為值。同樣地,如果是一個必需的字段,例如 ProductName ,如果從編輯界面中剔除了,那么此更新將會失敗并拋出一個 “ Column 'ProductName' does not allow nulls ” 異常。導致這一現象的原因是 ObjectDataSource 被配置為調用 ProductsBLL 類的 UpdateProduct 方法,它預期每一個產品字段都對應一個輸入參數。因此, ObjectDataSource 的 UpdateParameters 集合包含了該方法的每一個輸入參數。
如果我們希望提供一個允許最終用戶僅僅可以更新部分字段的數據 Web 服務器控件,那么我們需要在 ObjectDataSource 的 Updating 事件處理程序中編程設置缺失的 UpdateParameters 值,或者創建并調用一個預期部分字段的 BLL 方法。讓我們在接下來的步驟中探討。
特別地,讓我們創建一個在一個可編輯的 GridView 中僅顯示 ProductName 和 UnitPrice 字段的頁面。這個 GridView 的編輯界面將僅僅允許用戶更新兩個顯示的字段, ProductName 和 UnitPrice 。因為這個編輯界面僅僅提供產品的部分字段,我們需要創建一個 ObjectDataSource ,它使用現有的 BLL 的 UpdateProduct 方法并在 Updating 事件處理程序中編程設置產品的缺少的字段的值,或者我們需要創建一個新的 BLL 方法,它僅接受那些在 GridView 中已經定義的部分字段。在這一節里,我們使用后者,創建一個 UpdateProduct 方法的重載,它提取 3 個輸入參數: productName 、 unitPrice 和 productID :
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
if (products.Count == 0)
// no matching record found, return false
return false;
Northwind.ProductsRow product = products[0];
product.ProductName = productName;
if (unitPrice == null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value;
// Update the product record
int rowsAffected = Adapter.Update(product);
// Return true if precisely one row was updated, otherwise false
return rowsAffected == 1;
}
跟原有的 UpdateProduct 方法類似,這個重載方法首先檢查是否在數據庫中存在一個指定 ProductID 的產品。如果不存在,它返回 false ,指示更新產品信息的請求失敗。否則,它因而更新現存的產品記錄的 ProductName 和 UnitPrice 字段并通過調用 TableAdapter 的 Update() 方法提交此更新,傳入 ProductsRow 實例。
通過這些對我們的 ProductsBLL 類的額外處理,我們現在可以創建一個簡單 GridView 界面。打開 EditInsertDelete 文件夾中的 DataModificationEvents.aspx ,添加一個 GridView 控件到頁面。新建一個 ObjectDataSource 并配置它使用 ProductsBLL 類,它的 Select() 方法映射到 GetProducts , Update() 方法映射到僅接受 productName 、 unitPrice 和 productID 輸入參數的 UpdateProduct 方法重載。圖 2 展示了映射 ObjectDataSource 的 Update() 方法到 ProductsBLL 類的新的 UpdateProduct 方法重載時的數據源配置向導。
圖
2:
映射
ObjectDataSource
的
Update()
方法到新的
UpdateProduct
重載
因為我們的例子將僅僅需要編輯數據的能力,不需要插入或刪除記錄,那么花些時間明確地指明該 ObjectDataSource 的 Insert() 和 Delete() 方法不會映射到 ProductsBLL 類的任何方法 -- 通過到 INSERT 和 DELETE 的 tab 頁并從下拉列表中選擇(無)。
圖
3:
在
INSERT
和
DELETE
的
Tab
頁,從下拉列表中選擇(無)
完成了此向導后,從 GridView 的職能標記里勾選上啟用編輯。
完成了此數據源配置向導并綁定到 GridView 后, Visual Staudio 就已經添加好它們的聲明語法。到源視圖察看該 ObjectDataSource 的聲明標記,它將如下所示:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts" TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
因為 ObjectDataSource 的 Insert() 和 Delete() 方法沒有映射,也就沒有 InsertParameters 或者 DeleteParameters 片段。此外,因為方法映射到 UpdateProduct 方法重載,它僅接受 3 個輸入參數, UpdateParameters 片段也就僅包含 3 個 Parameter 實例。
注意到 ObjectDataSource 的屬性被設置為 original_{0} 。這個屬性是使用數據源配置向導時 Visual Studio 自動設置的。因此,由于我們的 BLL 方法不需要傳入原始的 ProductID 值,從 ObjectDataSource 的聲明語法中刪除所有這些屬性設置。
注意 : If you 如果你只是簡單地在設計視圖里從屬性窗口清除 OldValuesParameterFormatString 屬性的值,這個屬性會依舊存在于聲明語法里,但會被設置為一個空字符串。要么從聲明語法里把該屬性通通刪掉,要么從屬性窗口,設置它的值為默認值: {0} 。
雖然 ObjectDataSource 僅僅包含對 productName 、 unitPrice 和 productID 的 UpdateParameters , Visual Studio 還是為產品的每一個字段添加一個綁定列或 CheckBoxField 。
圖
4:
對應產品的每一個字段,
GridView
都包含一個
BoundField
或
CheckBoxField
當最終用戶編輯一個產品并點擊它的保存按鈕( Update ),該 GridView 遍歷那些可編輯的字段,然后把用戶輸入的值賦值到 ObjectDataSource 的 UpdateParameters 集合里對應的參數。如果沒有對應的參數, GridView 則添加一個到參數集合里。因此,如果我們的 GridView 包含對應產品的所有字段的綁定列或 CheckBox 列,那么 ObjectDataSource 則會調用能接受這些參數的方法重載,而不顧 ObjectDataSource 的聲明標記指定只接受 3 個輸入參數的事實(見圖 5 )。類似地,如果存在某些由 GridView 非只讀列構成的組合,而沒有一個 UpdateProduct 重載能接受相應的參數,則會在試圖保存時引發一個異常。
圖
5: GridView
將添加參數到
ObjectDataSource
的
UpdateParameters
集合
為了確保 ObjectDataSource 調用僅接受 productName 、 unitPrice 和 productID 參數 的 UpdateProduct 重載,我們需要限定 GridView 僅包含 ProductName 和 UnitPrice 這兩個可編輯的列。這可以通過刪除其他綁定列和 CheckBox 列,或者把這些列的 ReadOnly 屬性設置為 true 實現,又或者上述兩種方法結合使用。在本節里讓我們簡單地刪除除了 ProductName 和 UnitPrice 綁定列以外的 GridView 的所有列,然后, GridView 的聲明標記將如下所示:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" EnableViewState="False">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
即使重載預期 3 個輸入參數,在我們的 GridView 里僅包含兩個綁定列。這是因為 productID 輸入參數是一個主鍵( primary key )的值,它通過當前編輯行的 DataKeyNames 屬性傳入值。
我們的 GridView 控件,連同這個 UpdateProduct 重載,允許一個用戶僅僅編輯產品的名稱和單價而不會丟失產品的其他字段。
圖
6:
僅允許編輯
ProductName
和
Unit
Price
的界面
完善 UnitPrice 格式化
雖然圖 6 所示的 GridView 實例能夠正常工作, UnitPrice 字段還完全未被格式化,導致顯示價格時缺少貨幣符號,還有 4 個小數位。為了在非編輯狀態的行應用貨幣格式,只需要簡單地設置 UnitPrice 綁定列的 DataFormatString 屬性為 {0:c} ,還有它的 HtmlEncode 屬性為 false 。
圖
7:
設置
UnitPrice
綁定列的
DataFormatString
和
HtmlEncode
屬性
通過此項更改,處于非編輯狀態的行將價格格式化為貨幣;然而,當前編輯的行,仍然顯示為沒有貨幣符號并保留四位小數。
圖
8:
現在,非編輯狀態的行格式化為貨幣值
通過設置此綁定列的 ApplyFormatInEditMode 屬性為 true (默認為 false ),可以把 DataFormatString 屬性里指定的格式化指令應用到編輯界面。
圖
9:
設置此綁定列的
ApplyFormatInEditMode
屬性為
true
通過這個更改,當前編輯行里顯示的 UnitPrice 值也被格式化為貨幣。
圖
10:
現在,當前編輯行的值也被格式化為貨幣
然而,如果把產品價格更新為文本框里帶貨幣符號的值 – 例如 $19.00 – 則會拋出一個 FormatException 異常。當 GridView 嘗試把用戶提供的值賦值到 ObjectDataSource 的 UpdateParameters 集合,它無法把 UnitPrice 字符串“ $<chmetcnv w:st="on" unitname="”" sourcevalue="19" hasspace="False" negative="False" numbertype="1" tcsc="0">19.00<span><span>”</span></span></chmetcnv> 轉換成參數要求的 decimal 類型(見圖 11 )。為了補救這個問題我們可以為 GridView 的 RowUpdating 事件添加一個事件處理程序并讓它把用戶輸入的 UnitPrice 格式化為貨幣格式的 decimal 。
這個 GridView 的 RowUpdating 事件接受的第二個參數是一個 GridViewUpdateEventArgs 類型的對象,它包含一個 NewValues 字典,當中的每一個屬性保存著用戶輸入的值,準備賦值到 ObjectDataSource 的 UpdateParameters 集合。我們可以重寫現有的 NewValues 集合中的 UnitPrice 值為一個貨幣金額,通過下面的事件處理程序中的代碼進行解析:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
if (e.NewValues["UnitPrice"] != null)
e.NewValues["UnitPrice"] = decimal.Parse(e.NewValues["UnitPrice"].ToString(), System.Globalization.NumberStyles.Currency);
}
如果用戶提供了一個諸如“ $<chmetcnv w:st="on" unitname="”" sourcevalue="19" hasspace="False" negative="False" numbertype="1" tcsc="0">19.00<span><span>”</span></span></chmetcnv> 的 UnitPrice 值,這個值會被通過 Decimal.Parse 計算并解析為貨幣金額的值重寫。這將正確的解析貨幣值,無論是貨幣符號、逗號、小數點、等等,并使用 System.Globalization 命名空間的 NumberStyles 枚舉 。
圖 11 展示因用戶輸入的 UnitPrice 值帶有貨幣符號引起的問題,還展示了如果利用 GridView 的 RowUpdating 事件處理程序從而正確地解析這樣的輸入。
圖
11:
現在,當前編輯行的
UnitPrice
值被格式化為貨幣金額
第二步 : 阻止 NULL UnitPrices
雖然數據庫被配置為允許 Products 表里的 UnitPrice 字段為 NULL 值,但我們可能希望防止用戶訪問這個特別的頁面并指定一個空的 UnitPrice 值。更確切地說,如果用戶在編輯一個產品行記錄時忘記輸入一個 UnitPrice 值, 與其保存這個結果到數據庫,我們還不如給用戶顯示一個提示信息,自始至終這個頁面,任何的對產品的編輯必須指定一個價格。
傳入到 GridView 的事件處理程序的 GridViewUpdateEventArgs 對象包含一個 Cancel 屬性,如果把它設置為 true ,則中止這個更新過程。讓我們擴展 RowUpdating 事件處理程序,設置 e.Cancel 為 true 并顯示一個信息說明為什么在 NewValues 集合里的 UnitPrice 值為 null 。
首先,添加一個 Label 服務器控件到頁面并命名為 MustProvideUnitPriceMessage 。這個 Label 控件將顯示用戶是否在更新一個產品時忘記指定一個 UnitPrice 值。設置這個 Label 的 Text 屬性為“您必須為產品提供一個價格?!?。我也已經在 Styles.css 文件中添加了一個名為 Warning 的新 CSS 類別,定義如下:
.Warning
{
color: Red;
font-style: italic;
font-weight: bold;
font-size: x-large;
}
最后,設置 Label 的 CssClass 屬性為 Warning 。這樣設計器中將在 GridView 上方顯示這個紅色、斜體、加粗、并且較大字體的警告信息。
圖
12:
一個
Label
控件已被添加到
GridView
上方
默認地,這個 Label 控件隱藏,那么在 Page_Load 事件處理程序中設置它的 Visible 屬性為 false 。
protected void Page_Load(object sender, EventArgs e)
{
MustProvideUnitPriceMessage.Visible = false;
}
如果用戶嘗試更新一個產品并不指定 UnitPrice 值,我們希望取消這個更新并顯示警告標簽。在 GridView 的 RowUpdating 事件處理程序中增加如下的代碼:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
if (e.NewValues["UnitPrice"] != null)
e.NewValues["UnitPrice"] = decimal.Parse(e.NewValues["UnitPrice"].ToString(), System.Globalization.NumberStyles.Currency);
else
{
// Show the Label
MustProvideUnitPriceMessage.Visible = true;
// Cancel the update
e.Cancel = true;
}
}
如果一個用戶試圖保存一個產品并不指定價格,這個更新操作就被取消并顯示一個有用的提示信息。雖然數據庫(和業務邏輯)允許 NULL 值的 UnitPrice ,但這個特定的 ASP.NET 頁面不允許。
圖
13:
用戶不能讓
UnitPrice
為空
到目前為止我們看過了如何使用 GridView 的 RowUpdating 事件來編程改變賦值到 ObjectDataSource 的 UpdateParameters 集合的參數值,還有如何完全地取消這個更新過程。這些思想也可以延展至 DetailsView 和 FormView 控件并且應用到插入或刪除。
這些任務也可以在 ObjectDataSource 這一層通過的 Inserting 、 Updating 和 Deleting 事件處理程序完成。這些事件在隱含對象的關聯方法被調用前觸發,并且提供一個更改輸入參數集合或者完全取消此操作的最后機會。對應這 3 個事件的事件處理程序傳入一個 ObjectDataSourceMethodEventArgs 類型的對象,我們對它的這兩個屬性感興趣:
· Cancel ,它如果被設置為 true ,取消執行中的操作
· InputParameters ,它是 InsertParameters 、 UpdateParameters 或 DeleteParameters 的集合,這取決于這是 Inserting 、 Updating 、 還是 Deleting 事件的事件處理程序
為了舉例說明在 ObjectDataSource 這一層如何處理參數的值,讓我們在頁面里包含一個 DeailsView ,它允許用戶新增一個新的產品記錄。這個 DetailsView 將用作提供一個快捷的方式添加一個新的產品記錄到數據庫。為了在新增產品時保持界面一致,我們僅允許用戶輸入 ProductName 和 UnitPrice 字段。作為默認值,這些在 DetailsView 的插入界面提供的值將被設置為一個數據庫的 NULL 值。不過,我們可以使用 ObjectDataSource 的 Inserting 事件注入不同的默認值,正如我們馬上要看的。
第三步 : 提供一個添加新產品的界面
在 GridView 的上方,從工具箱里拖放一個 DetailsView 控件到設計器,清空它的 Height 和 Width 屬性,并將它綁定到頁面中已經存在的 ObjectDataSource 。這將為產品的每一個字段添加一個綁定列或 CheckBox 列。因為我們希望用這個 DetailsView 控件來添加新產品,我們需要從它的職能標記里勾選啟用插入這一項;然而并沒有這一項,這是因為此 ObjectDataSource 的 Insert() 方法還沒有映射到 ProductsBLL 類的方法(回想起我們在配置數據源時設置了這個映射為(無) – 見圖 3 )。
為了再次配置這個 ObjectDataSource ,從它的職能標記中選擇“配置數據源”的鏈接,載入向導。第一屏允許你更改 ObjectDataSource 綁定到的隱含對象;讓它依舊是 ProductsBLL 。下一屏列出從 ObjectDataSource 到隱含對象的方法的映射。盡管我們已經明確地指定 Insert() 和 Delete() 不映射到任何方法,然而如果你到 INSERT 和 DELETE 的 tab 頁你還是會看到那里有一個映射。這是因為 ProductsBLL 的 AddProduct 和 DeleteProduct 方法使用了 DataObjectMethodAttribute 指出它們分別是為 Insert() 和 Delete() 服務的默認的方法。因此, ObjectDataSource 向導在每次運行時都會自動地選擇它們,除非那里被明確地指定了一個別的值。
讓 Insert() 方法依舊指向 AddProduct 方法,不過再次從 DELETE 的 tab 頁的下拉列表中選擇“ ( 無 ) ”。
圖
14:
從
INSERT
的
Tab
頁的下拉列表中選擇
AddProduct
方法
圖
15:
從
DELETE
的
Tab
頁的下拉列表中選擇
(
無
)
完成了這些更改后,該 ObjectDataSource 的聲明語法中將包含一個 InsertParameters 集合,如下所示:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetProducts"
TypeName="ProductsBLL" UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating" InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="supplierID" Type="Int32" />
<asp:Parameter Name="categoryID" Type="Int32" />
<asp:Parameter Name="quantityPerUnit" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="unitsInStock" Type="Int16" />
<asp:Parameter Name="unitsOnOrder" Type="Int16" />
<asp:Parameter Name="reorderLevel" Type="Int16" />
<asp:Parameter Name="discontinued" Type="Boolean" />
</InsertParameters>
</asp:ObjectDataSource>
再次運行向導導致重新添加 OldValuesParameterFormatString 屬性。把這個屬性設置為默認值( {0} )或者從聲明語法中把它們完全刪除。
隨著 ObjectDataSource 提供插入數據的能力,現在 DetailsView 的職能標記里包含“啟用插入”的 checkbox ;回到設計器并勾選這一項。然后,減少 DetailsView 的列直道它只包含兩個綁定列 - ProductName 和 UnitPrice ,還有一個 CommandField 。此時 DetailsView 的聲明語法將如下所示:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" EnableViewState="False">
<Fields>
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
圖 16 展現的是在此時通過瀏覽器查看的頁面。正如你所看到的, DetailsView 列出第一個產品( Chai )的名稱和價格。不過,我們需要的是一個插入界面來提供一個用戶快速增加一個新產品到數據庫的手段。
圖
16:
該
DetailsView
當前呈現在只讀模式
為了展示插入模式的 DetailsView 我們需要設置 DefaultMode 屬性為 Inserting 。這讓 DetailsView 在第一次訪問和插入一條新紀錄之后,它都呈現在插入模式。如圖 17 所示,這樣的一個 DetailsView 提供了一個快捷的界面用以添加新記錄。
圖
17:
這個
DetailsView
提供了一個快速添加新產品的界面
當用戶輸入一個產品名稱和價格(例如“ Acme Wate ”和 1.99 ,如圖 17 )并點擊插入按鈕,發生回傳并且開始插入的工作流程,直到最后添加一個新產品記錄到數據庫。 DetailsView 維持在它的插入界面,并且 GridView 自動地重現綁定到它的數據源,目的是為了包含新增加的產品,如圖 18 所示。
圖
18:
產品“
Acme Water
”已經被添加到數據庫
雖然圖 18 的 GridView 中沒有顯示出來, DetailsView 界面里缺少的產品字段 – CategoryID 、 SupplierID 、 QuantityPerUnit 、等等 – 被賦上一個數據庫 NULL 值。你可以通過履行下面一個步驟來看到這一點:
1. 到 Visual Studio 的服務器資源管理器
2. 展開 NORTHWND.MDF 數據庫節點
3. 在 Products 數據表節電上右鍵點擊
4. 選擇“顯示表數據”
這將列出 Products 表中的所有記錄。如圖 19 所示,除了 ProductID 、 ProductName 和 UnitPrice 字段,我們的新產品的其它字段都為 NULL 值。
圖
19:
未在
DetailsView
中提供的產品的其它字段被賦予
NULL
值
我們可能希望給予一個或幾個這些字段的值一個默認值,而不是 NULL ,要么是因為 NULL 并非最佳的默認項,要么是因為數據庫字段本身不允許 NULL 值。為了實現這一點,我們可以編程設置這些 DetailsView 的 InputParameters 集合里的參數值。這項工作可以在 DetailsView 的 ItemInserting 事件處理程序中完成,或者在 ObjectDataSource 的 Inserting 事件處理程序。因為我們已經看過了如何在數據 Web 服務器控件中如何使用 pre- 和 post-level 的事件,這次讓我們探究一下 ObjectDataSource 的事件。
第四步 : 給 CategoryID 和 SupplierID 參數賦值
在這里我們假設當我們的應用程序通過這個界面添加一個新產品時應該給 CategoryID 和 SupplierID 字段賦值為 1 。如之前提及的, ObjectDataSource 控件有一對 pre- 和 post-level 的事件發生在數據更改過程中。當它的 Insert() 方法被調用時, ObjectDataSource 首先觸發它的 Inserting 事件,然后調用它的 Insert() 方法所映射到的業務方法,最后觸發 Inserted 事件。這個 Inserting 事件處理程序提供給我們一個處理輸入參數或者徹底取消此操作的最后機會。
注意 : 在一個真實的應用程序中你很可能希望既讓用戶指定 category 和 supplier 的值,又希望基于一定的標準和業務邏輯的基礎上選擇這個值(而不是盲目地選擇 ID 為 1 )。不管如何,這個例子闡明了如何在 ObjectDataSource 的 pre-level 的事件中編程設置一個輸入參數的值。
花些時間為 ObjectDataSource 的 Inserting 事件創建一個事件處理程序。注意到該事件處理程序的第二個輸入參數是一個 ObjectDataSourceMethodEventArgs 類型的對象,它有一個屬性來存取參數集合( InputParameters ),還有一個屬性用來取消此操作( Cancel )。
protected void ObjectDataSource1_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
{
}
此時, InputParameters 屬性包含了通過 DetailsView 賦值到 ObjectDataSource 的 InsertParameters 集合。為了修改這些參數里的一個值,簡單地使用: e.InputParameters[" paramName "] = value 。所以,為了設置 CategoryID 和 SupplierID 為 1 ,把 Inserting 事件處理程序調整為如下:
protected void ObjectDataSource1_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
{
e.InputParameters["CategoryID"] = 1;
e.InputParameters["SupplierID"] = 1;
}
這次當我們添加一個新產品(例如 Acme Soda ),這個新產品的 CategoryID 和 SupplierID 字段被賦值為 1 (見圖 20 )。
圖
20:
現在,新產品的
CategoryID
和
SupplierID
字段被設置為
1
總結
在編輯、插入和刪除的過程中,無論數據 Web 服務器控件還是 ObjectDataSource 都會發生許多 pre- 和 post-level 的事件。在這一節里,我們研究了 pre-level 的事件,并看到了如何在數據 Web 服務器控件和 ObjectDataSource 的事件里使用它們來自定義輸入參數或取消當前的數據更改操作。下一節,我們將看看創建和使用 post-level 的事件的事件處理程序。
祝編程快樂!
作者簡介
Scott Mitchell ,著有六本 ASP/ASP.NET 方面的書,是 4GuysFromRolla.com 的創始人,自 1998 年以來一直應用微軟 Web 技術。 Scott 是個獨立的技 術咨詢顧問,培訓師,作家,最近完成了將由 Sams 出版社出版的新作, 24 小時內精通 ASP.NET 2.0 。他的聯系電郵為 mitchell@4guysfromrolla.com ,也可以通過他的博客 http://ScottOnWriting.NET 與他聯系。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
