導(dǎo)言
一般控件(比如GridView)顯示數(shù)據(jù)的時(shí)候?qū)?shù)據(jù)只能讀取,而需要處理數(shù)據(jù)的功能是非常常見(jiàn)的.典型的情況是為每行數(shù)據(jù)添加一個(gè)Button, LinkButton, 或ImageButton . 當(dāng)點(diǎn)擊這些button時(shí),數(shù)據(jù)會(huì)PostBack,執(zhí)行一些服務(wù)器端的代碼. 一條條的編輯或刪除數(shù)據(jù)是最常見(jiàn)的情況.實(shí)際上,編輯和刪除是如此常見(jiàn),從概述插入、更新和刪除數(shù)據(jù) 開(kāi)始, 我們可以看到GridView, DetailsView, 和 FormView可以零代碼的完成這些功能.
除了編輯和刪除button,GridView, DetailsView, and FormView 也可以包含一些執(zhí)行自定義服務(wù)器端代碼的Buttons, LinkButtons, 或 ImageButtons .在這一章我們來(lái)看看如何向一個(gè)GridView 或 DetailsView 里添加自定義的button.我們還將創(chuàng)建一個(gè)根據(jù)supplier進(jìn)行分頁(yè)的頁(yè)面.對(duì)每個(gè)給定的supplier,FormView會(huì)顯示它的相關(guān)信息,外加一個(gè)Button .點(diǎn)擊這個(gè)Button 時(shí),所有相關(guān)products會(huì)被標(biāo)記為停止使用.另外,GridView 會(huì)列出選定的supplier提供的所有product ,并且每一行會(huì)包含“Increase Price”和“Discount Price”兩個(gè)Button.這兩個(gè)Button用來(lái)提高或降低10%的product單價(jià)(見(jiàn)圖一).
圖 1: FormView和GridView 都包含了執(zhí)行自定義行為的Button
第一步: 添加一個(gè)Button 教程頁(yè)
在研究如何添加自定義button之前,我們先花一點(diǎn)時(shí)間在網(wǎng)站里創(chuàng)建一些頁(yè),這些頁(yè)會(huì)在本指南里用到.先添加一個(gè)名為CustomButtons的文件夾,然后添加如下的兩個(gè)頁(yè).添加頁(yè)的時(shí)候確保每頁(yè)都選擇了Site.master作為母板頁(yè).
Default.aspx
CustomButtons.aspx
圖 2: 添加本指南需要的頁(yè)面
象其它文件夾一樣,CustomButtons 文件夾里的Default.aspx 用來(lái)列出教程章節(jié).記得SectionLevelTutorialListing.ascx 這個(gè)用戶控件提供了這個(gè)功能.因此,從解決方案瀏覽里將這個(gè)用戶控件拖到頁(yè)面上.
圖 3: 添加SectionLevelTutorialListing.ascx 用戶控件 到Default.aspx
最后,將這些頁(yè)的地址加到 Web.sitemap 的條目里.在Paging and Sorting siteMapNode>之后添加下面的標(biāo)記.
siteMapNode
title="Adding Custom Buttons"
description="Samples of Reports that Include Buttons for Performing
Server-Side Actions"
url="~/CustomButtons/Default.aspx">
siteMapNode
title="Using ButtonFields and Buttons in Templates"
description="Examines how to add custom Buttons, LinkButtons,
or ImageButtons as ButtonFields or within templates."
url="~/CustomButtons/CustomButtons.aspx" />
/siteMapNode>
修改完Web.sitemap后,在瀏覽器里看一下本教程站點(diǎn),現(xiàn)在左邊的菜單里包含了編輯,插入,刪除教程的項(xiàng).
圖 4: Site Map包含了添加自定義button教程
第二步: 添加一個(gè)列出 Supplier的FormView
我們首先來(lái)添加一個(gè)列出suppliers的FormView .正如在導(dǎo)言里討論的那樣,FormView根據(jù)supplier分頁(yè),并在GridView顯示supplier 提供的所有product .另外FormView 會(huì)包含一個(gè)Button .當(dāng)點(diǎn)擊時(shí),所有相關(guān)products會(huì)被標(biāo)記為停止使用.在我們?yōu)镕ormView添加自定義button之前,我們首先創(chuàng)建顯示supplier 信息的FormView .
打開(kāi)CustomButtons文件夾里的CustomButtons.aspx 頁(yè),從工具箱里拖一個(gè)FormView進(jìn)來(lái),將FormView的ID設(shè)置為Suppliers.打開(kāi)FormView的智能標(biāo)簽,創(chuàng)建一個(gè)名為SuppliersDataSource的ObjectDataSource.
圖 5: 創(chuàng)建一個(gè)名為SuppliersDataSource的ObjectDataSource
選擇SuppliersBLL 類的GetSuppliers()方法配置ObjectDataSource(見(jiàn)圖6).由于這個(gè)FormView沒(méi)有提供修改supplier 信息的界面,所以在UPDATE 標(biāo)簽的下拉列表里選擇None.
圖 6: 使用 SuppliersBLL 類的GetSuppliers() 方法配置數(shù)據(jù)源
數(shù)據(jù)源配置完成后,Visual Studio會(huì)生成一個(gè)InsertItemTemplate,一個(gè)EditItemTemplate和一個(gè)FormView的ItemTemplate.去掉InsertItemTemplate 和EditItemTemplate ,修改ItemTemplate,讓它只顯示supplier的公司名,電話號(hào)碼.最后,在智能標(biāo)簽里選中Enable Paging checkbox 或者設(shè)置AllowPaging 屬性為True.完成這些后,你的聲明標(biāo)記看起來(lái)應(yīng)該和以下差不多:
asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
DataSourceID="SuppliersDataSource" EnableViewState="False" AllowPaging="True">
ItemTemplate>
h3>
asp:Label ID="CompanyName" runat="server"
Text='%# Bind("CompanyName") %>' />
/h3>
b>Phone:/b>
asp:Label ID="PhoneLabel" runat="server" Text='%# Bind("Phone") %>' />
/ItemTemplate>
/asp:FormView>
asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
/asp:ObjectDataSource>
圖 7: FormView列出當(dāng)前選定的Supplier的CompanyName and Phone
第三步 : 添加一個(gè)GridView,用來(lái)列出某個(gè)Supplier的所有Product
在添加“Discontinue All Products”Button 前,先在FormView 下面添加一個(gè)GridView . 設(shè)置ID 為SuppliersProducts,添加一個(gè)名為SuppliersProductsDataSource的ObjectDataSource .
圖 8: 創(chuàng)建一個(gè)名為SuppliersProductsDataSource的ObjectDataSource
選擇ProductsBLL 類的GetProductsBySupplierID(supplierID)方法配置ObjectDataSource(見(jiàn)圖9).雖然GridView 允許修改product的價(jià)格,但是并不使用的GridView自帶的編輯或刪除功能.因此在UPDATE, INSERT, and DELETE 標(biāo)簽的下拉列表里都選擇None.
圖 9: 使用ProductsBLL 類的GetProductsBySupplierID(supplierID) 方法配置數(shù)據(jù)源
由于GetProductsBySupplierID(supplierID)有一個(gè)輸入?yún)?shù),ObjectDataSource向?qū)?huì)提示我們配置這個(gè)參數(shù).為了將SupplierID 從FormView傳過(guò)來(lái),在參數(shù)來(lái)源的下來(lái)列表里選擇Control,在ControlID 下拉列表里選擇Suppliers (在第二步里創(chuàng)建的FormView 的ID).
圖 10: 指定 supplierID 參數(shù)的來(lái)源為Suppliers FormView
完成了ObjectDataSource 向?qū)Ш?GridView 里的每一行product會(huì)包含一個(gè)BoundField 和一個(gè)CheckBoxField . 我們來(lái)精簡(jiǎn)一下,只顯示Discontinued CheckBoxField,ProductName 和UnitPrice .我們修改UnitPrice 列的格式為貨幣. 你的GridView 和SuppliersProductsDataSource ObjectDataSource的聲明標(biāo)記看起來(lái)應(yīng)該和下面差不多:
asp:GridView ID="SuppliersProducts" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
EnableViewState="False" runat="server">
Columns>
asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
asp:BoundField DataField="UnitPrice" HeaderText="Price"
SortExpression="UnitPrice" DataFormatString="{0:C}"
HtmlEncode="False" />
asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
/Columns>
/asp:GridView>
asp:ObjectDataSource ID="SuppliersProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
SelectParameters>
asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
/SelectParameters>
/asp:ObjectDataSource>
現(xiàn)在我們的顯示了一個(gè)主/從表,用戶通過(guò)在上面的FormView 里選擇一個(gè)supplier ,在下方的GridView 里就可以看到這個(gè)supplier 提供的products.
圖11是在FormView里選擇Tokyo Traders supplier 的截圖.
圖 11: 在GridView顯示選定的Supplier的產(chǎn)品
第四步: 創(chuàng)建DAL和BLL層的停止使用Supplier的所有Products 的方法
在FormView 添加discontinue button前,我們首先需要在DAL 和BLL 里添加完成這個(gè)功能的方法.這個(gè)方法的名字為DiscontinueAllProductsForSupplier(supplierID). 當(dāng)點(diǎn)擊FormView的Button 時(shí),我們會(huì)調(diào)用Business Logic Layer里的這個(gè)方法,并將選定的supplier的SupplierID傳進(jìn)去.BLL 會(huì)繼續(xù)調(diào)用Data Access Layer的相關(guān)方法,這個(gè)方法會(huì)向數(shù)據(jù)庫(kù)提交一個(gè)停止使用選定的supplier的products的UPDATE語(yǔ)句
象在以前的教程里所做的那樣,我們使用自底向上的方法,首先創(chuàng)建DAL 的方法,然后是BLL ,最后在 ASP.NET page里實(shí)現(xiàn)這個(gè)功能.打開(kāi)App_Code/DAL文件夾里的Northwind.xsd ,為ProductsTableAdapter 添加一個(gè)新方法(右鍵點(diǎn)擊ProductsTableAdapter ,選擇Add Query).這樣彈出TableAdapter Query 的配置向?qū)?首先指定DAL 需要使用的SQL .
圖 12: 使用SQL Statement創(chuàng)建DAL 方法
接著,向?qū)?huì)詢問(wèn)我們創(chuàng)建哪種類型的query .由于DiscontinueAllProductsForSupplier(supplierID)需要更新Products表,為指定的supplierID 的所有products的Discontinued 字段設(shè)置為1,因此我們需要?jiǎng)?chuàng)建一個(gè)更新數(shù)據(jù)的query .
圖 13: 選擇UPDATE Query的類型
下一個(gè)向?qū)э@示的窗口提供了TableAdapter的已經(jīng)存在的UPDATE 語(yǔ)句,它會(huì)updates 在Products DataTable定義的所有的字段.用下面的語(yǔ)句替換它:
UPDATE [Products] SET
Discontinued = 1
WHERE SupplierID = @SupplierID
輸入以上語(yǔ)句后點(diǎn)Next,最后一個(gè)向?qū)Т翱谛枰斎朐摲椒ǖ拿帧狣iscontinueAllProductsForSupplier.完成向?qū)Ш簏c(diǎn)Finish button.當(dāng)你回到DataSet 設(shè)計(jì)器時(shí)你應(yīng)該可以在ProductsTableAdapter 看到名為DiscontinueAllProductsForSupplier(@SupplierID)的方法.
圖 14: 為 DAL 的方法取名為 DiscontinueAllProductsForSupplier
完成Data Access Layer里的DiscontinueAllProductsForSupplier(supplierID)方法后,我們下一步的任務(wù)是創(chuàng)建Business Logic Layer里的相應(yīng)的方法.打開(kāi)ProductsBLL 類文件,添加以下內(nèi)容:
public int DiscontinueAllProductsForSupplier(int supplierID)
{
return Adapter.DiscontinueAllProductsForSupplier(supplierID);
}
這個(gè)方法僅僅是調(diào)用DAL里的DiscontinueAllProductsForSupplier(supplierID)方法,并傳遞提供的supplierID 參數(shù).如果有一些業(yè)務(wù)規(guī)則規(guī)定僅僅允許在一定的條件下supplier的products 才能被停止使用,那么這些規(guī)則應(yīng)該寫在這里(BLL).
注意:和ProductsBLL 類的UpdateProduct重載不一樣,DiscontinueAllProductsForSupplier(supplierID)的簽名不包括DataObjectMethodAttribute 屬性(System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>).這個(gè)將DiscontinueAllProductsForSupplier(supplierID) 方法從ObjectDataSource的配置數(shù)據(jù)源向?qū)У腢PDATE標(biāo)簽里的下拉列表中排除.我之所以忽略這個(gè)屬性是因?yàn)槲覀儠?huì)在ASP.NET page里直接通過(guò)event handler 調(diào)用DiscontinueAllProductsForSupplier(supplierID)方法.
第五步: 為FormView添加一個(gè)“Discontinue All Products” Button
完成了BLL 和 DAL 里的DiscontinueAllProductsForSupplier(supplierID)方法后,我們來(lái)做實(shí)現(xiàn)停止使用選定的supplier的所有product的功能最后一步:為 FormView的 ItemTemplate添加Button .我們將這個(gè)Button 添加在supplier的phone number下,Text為“Discontinue All Products”,ID為DiscontinueAllProductsForSupplier.你可以通過(guò)FormView的智能標(biāo)簽里的Edit Templates 來(lái)添加這個(gè)Button (見(jiàn)圖15),或直接修改代碼.
圖 15: 為FormView的ItemTemplate添加 “Discontinue All Products” Button
當(dāng)用戶點(diǎn)擊這個(gè)Button 時(shí),頁(yè)面會(huì)回發(fā),FormView的ItemCommand event被激發(fā).我們可以為這個(gè)事件創(chuàng)建一個(gè)event handler ,用來(lái)在Button 被點(diǎn)擊時(shí)執(zhí)行自定義代碼.注意,任何時(shí)候FormView里的任何Button, LinkButton, 或 ImageButton被點(diǎn)擊時(shí),ItemCommand 事件都會(huì)被激發(fā).這意味著當(dāng)用戶在FormView里從一個(gè)頁(yè)面跳到另一個(gè)頁(yè)面時(shí),ItemCommand 事件會(huì)被激發(fā).當(dāng)用戶點(diǎn)擊一個(gè)支持inserting, updating, 或 deleting的FormView里的New, Edit, 或 Delete 時(shí),ItemCommand 事件會(huì)被激發(fā).
既然無(wú)論點(diǎn)擊什么button時(shí), ItemCommand 都會(huì)被激發(fā),那么在event handler里我們需要判斷是“Discontinue All Products” Button 被點(diǎn)擊了還是其它的button.為了達(dá)到這個(gè)目的,我們可以通過(guò)設(shè)置Button 的CommandName來(lái)識(shí)別. 當(dāng)Button 被點(diǎn)擊后,CommandName 的值被傳到ItemCommand 的event handler,我們通過(guò)這個(gè)值來(lái)判斷被點(diǎn)擊的button是否是“Discontinue All Products” Button.設(shè)置“Discontinue All Products” Button的CommandName 為“DiscontinueProducts”.
最后我們?cè)诳蛻舳嗽黾右粋€(gè)確認(rèn)框來(lái)確保用戶真的想停止使用選擇的supplier的所有product.和我們?cè)跒閯h除數(shù)據(jù)添加客戶端確認(rèn) 里看到的一樣,這個(gè)可以用JavaScript來(lái)完成. 設(shè)置Button 的OnClientClick屬性為“return confirm('This will mark _all_ of this supplier/'s products as discontinued. Are you certain you want to do this?');”
asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
DataSourceID="SuppliersDataSource" EnableViewState="False"
AllowPaging="True">
ItemTemplate>
h3>asp:Label ID="CompanyName" runat="server"
Text='%# Bind("CompanyName") %>'>/asp:Label>/h3>
b>Phone:/b>
asp:Label ID="PhoneLabel" runat="server" Text='%# Bind("Phone") %>' />
br />
asp:Button ID="DiscontinueAllProductsForSupplier" runat="server"
CommandName="DiscontinueProducts" Text="Discontinue All Products"
OnClientClick="return confirm('This will mark _all_ of this supplier/'s
products as discontinued. Are you certain you want to do this?');" />
/ItemTemplate>
/asp:FormView>
下面,為FormView的 ItemCommand 事件創(chuàng)建event handler . 在這個(gè)event handler 里我們需要首先判斷“Discontinue All Products”Button是否被點(diǎn)擊了.如果是,我們就需要?jiǎng)?chuàng)建一個(gè)ProductsBLL 類的實(shí)例然后調(diào)用DiscontinueAllProductsForSupplier(supplierID)方法,并將FormView里選定的SupplierID 傳過(guò)去.
protected void Suppliers_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName.CompareTo("DiscontinueProducts") == 0)
{
// The "Discontinue All Products" Button was clicked.
// Invoke the ProductsBLL.DiscontinueAllProductsForSupplier(supplierID) method
// First, get the SupplierID selected in the FormView
int supplierID = (int)Suppliers.SelectedValue;
// Next, create an instance of the ProductsBLL class
ProductsBLL productInfo = new ProductsBLL();
// Finally, invoke the DiscontinueAllProductsForSupplier(supplierID) method
productInfo.DiscontinueAllProductsForSupplier(supplierID);
}
}
注意:在FormView 里當(dāng)前選定的supplier 的SupplierID 可以通過(guò)FormView的 SelectedValue property屬性獲取.SelectedValue 屬性返回FormView里顯示的記錄的第一個(gè)data key的值.FormView的DataKeyNames property在綁定ObjectDataSource 到FormView 時(shí)(第二步)會(huì)自動(dòng)的被設(shè)置為SupplierID .
ItemCommand event handler 創(chuàng)建完后,花點(diǎn)時(shí)間測(cè)試一下這個(gè)頁(yè)面.瀏覽Cooperativa de Quesos 'Las Cabras' supplier (在我這是FormView 里的第五個(gè)supplier ).這個(gè)supplier 提供兩種product, Queso Cabrales and Queso Manchego La Pastora,兩個(gè)都沒(méi)有停止使用的.
想象一下 Cooperativa de Quesos 'Las Cabras' 歇業(yè)了,因此它的產(chǎn)品都要被停止使用.點(diǎn)擊“Discontinue All Products” Button.會(huì)彈出一個(gè)確認(rèn)的對(duì)話框.
圖 16: Cooperativa de Quesos 'Las Cabras' 供應(yīng) 兩種有效的產(chǎn)品
如果在確定對(duì)話框里點(diǎn)擊OK,表單提交就會(huì)繼續(xù),ormView的ItemCommand 事件會(huì)被激發(fā).然后我們創(chuàng)建的event handler會(huì)執(zhí)行,調(diào)用DiscontinueAllProductsForSupplier(supplierID)方法,停止使用Queso Cabrales 和 Queso Manchego La Pastora這兩個(gè)產(chǎn)品.
如果你禁用了GridView的view state,每次postback時(shí)GridView 都會(huì)重新綁定,因此這兩種product被停止使用的狀態(tài)馬上就能顯示出來(lái)(見(jiàn)圖17).而如果沒(méi)有禁用GridView的view state,你需要手動(dòng)再次綁定數(shù)據(jù).
圖 17: 點(diǎn)擊 “Discontinue All Products” Button后, Supplier的 Products被更新
第六步: 為調(diào)整Product的價(jià)格,在Business Logic Layer 創(chuàng)建一個(gè)UpdateProduct
和FormView里的“Discontinue All Products” Button 一樣,為了在GridView 里添加提高或者降低product 的價(jià)格的button,我們首先添加Data Access Layer and Business Logic Layer 的方法.由于我們?cè)贒AL里已經(jīng)有一個(gè)更新單個(gè)產(chǎn)品記錄的方法,我們可以通過(guò)在BLL創(chuàng)建UpdateProduct 的重載方法來(lái)實(shí)現(xiàn)這個(gè)功能.
我們以前的UpdateProduct 包括一些product 字段作為輸入值,我們可以為指定的product更新這些字段.我們將做少量修改,傳遞ProductID 和調(diào)整單價(jià)的百分比.因?yàn)椴挥迷贉y(cè)定當(dāng)前product 的單價(jià),所以這樣的方法會(huì)讓我們?cè)贏SP.NET page 的cs文件里的代碼變的更簡(jiǎn)潔.
UpdateProduct 在本指南中使用的重載方法如下:
public bool UpdateProduct(decimal unitPriceAdjustmentPercentage, 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];
// Adjust the UnitPrice by the specified percentage (if it's not NULL)
if (!product.IsUnitPriceNull())
product.UnitPrice *= unitPriceAdjustmentPercentage;
// Update the product record
int rowsAffected = Adapter.Update(product);
// Return true if precisely one row was updated, otherwise false
return rowsAffected == 1;
}
這個(gè)方法通過(guò)DAL的GetProductByProductID(productID)方法獲取指定product 的信息.它會(huì)檢查product的單價(jià)是否是空值.如果是,這個(gè)價(jià)格就不被更改.如果不是,product的UnitPrice 將根據(jù)指定的百分比更改(unitPriceAdjustmentPercent)
第七步: 在GridView里添加升價(jià)和降價(jià)的Button
GridView (和DetailsView)都是字段的集合.除了BoundFields, CheckBoxFields, and TemplateFields這幾個(gè)字段外,ASP.NET還包含ButtonField.就象它的名字一樣,ButtonField提供一個(gè)Button, LinkButton, 或 ImageButton列.和FormView一樣,點(diǎn)擊GridView 里的任何一個(gè)button— 分頁(yè),編輯或刪除,排序等— 頁(yè)面都會(huì)回發(fā) ,并激發(fā)GridView的RowCommand event.
ButtonField 有一個(gè)CommandName 屬性,可以用來(lái)指派特定的值給每個(gè)Button的CommandName 屬性.象FormView一樣,CommandName 的值用來(lái)在RowCommand event handler 里判斷哪個(gè)button被點(diǎn)擊了.
現(xiàn)在我們來(lái)為GridView添加兩個(gè)ButtonField,一個(gè)的text為“Price +10%” ,另外一個(gè)的text為“Price -10%”. 點(diǎn)擊GridView的智能標(biāo)簽里的Edit Columns link ,在左上的列表里選擇ButtonField 類,點(diǎn)添加.
圖 18: 為GridView添加兩個(gè)ButtonField
移動(dòng)這兩個(gè)ButtonField 到GridView 的前兩列.分別設(shè)置ButtonField的text為 “Price +10%” and “Price -10%”,CommandName 為“IncreasePrice” and “DecreasePrice”,.默認(rèn)情況下,ButtonField 里的button為L(zhǎng)inkButtons,這個(gè)是可通過(guò)ButtonField的ButtonType property屬性來(lái)修改的.我們將這兩個(gè)ButtonField設(shè)置為常規(guī)的push button.因此,設(shè)置ButtonType 屬性為Button.圖19顯示了設(shè)置完成后的Fields 對(duì)話框的樣子.而后面一個(gè)圖則為GridView的頁(yè)面代碼.
圖 19: 配置 ButtonField的 Text, CommandName, and ButtonType 屬性
asp:GridView ID="SuppliersProducts" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
EnableViewState="False">
Columns>
asp:ButtonField ButtonType="Button" CommandName="IncreasePrice"
Text="Price +10%" />
asp:ButtonField ButtonType="Button" CommandName="DecreasePrice"
Text="Price -10%" />
asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
asp:BoundField DataField="UnitPrice" HeaderText="Price"
SortExpression="UnitPrice" DataFormatString="{0:C}"
HtmlEncode="False" />
asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
/Columns>
/asp:GridView>
創(chuàng)建ButtonField完成后,最后一步是為GridView的RowCommand 事件創(chuàng)建event handler .當(dāng)“Price +10%”或“Price -10%”button被點(diǎn)擊時(shí),這個(gè)event handler需要判斷被點(diǎn)擊的那一行的ProductID ,然后調(diào)用ProductsBLL 類的UpdateProduct 方法,并將UnitPrice 的調(diào)整折扣和ProductID傳進(jìn)去.下來(lái)的代碼會(huì)完成以上工作:
protected void SuppliersProducts_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.CompareTo("IncreasePrice") == 0 ||
e.CommandName.CompareTo("DecreasePrice") == 0)
{
// The Increase Price or Decrease Price Button has been clicked
// Determine the ID of the product whose price was adjusted
int productID =
(int)SuppliersProducts.DataKeys[Convert.ToInt32(e.CommandArgument)].Value;
// Determine how much to adjust the price
decimal percentageAdjust;
if (e.CommandName.CompareTo("IncreasePrice") == 0)
percentageAdjust = 1.1M;
else
percentageAdjust = 0.9M;
// Adjust the price
ProductsBLL productInfo = new ProductsBLL();
productInfo.UpdateProduct(percentageAdjust, productID);
}
}
為了判斷被點(diǎn)擊“Price +10%” or “Price -10%” button 的那一行的ProductID ,我們需要用到GridView的DataKeys 集合.這個(gè)集合包含了GridView 的行的所有值.由于GridView在綁定到ObjectDataSource 時(shí),DataKeyNames 被Visual Studio設(shè)置為ProductID ,DataKeys(rowIndex).Value 提供了指定rowIndex的ProductID .
ButtonField 會(huì)將被點(diǎn)擊的button所在row 的rowIndex 自動(dòng)傳到e.CommandArgument 參數(shù)里.因此,我們用Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)來(lái)獲取被點(diǎn)擊“Price +10%” or “Price -10%” button的行的ProductID .
和“Discontinue All Products” button里一樣,如果你禁用了GridView的view state屬性,每次postback時(shí)GridView 都會(huì)重新綁定.如果你這么做,你需要手動(dòng)再次綁定.
圖20顯示當(dāng)瀏覽Grandma Kelly's Homestead提供的product的頁(yè).圖21顯示當(dāng)Grandma's Boysenberry Spread 的“Price +10%” button 被點(diǎn)擊了兩次和Northwoods Cranberry Sauce的“Price -10%” button被點(diǎn)擊了一次的頁(yè)面.
圖20: GridView 包含“Price +10%” 和 “Price -10%” 兩個(gè)Buttons
圖 21: 第一和第三個(gè)產(chǎn)品的價(jià)格通過(guò)“Price +10%” and “Price -10%” Buttons更新
注意:GridView (和DetailsView)同樣可以將Buttons,LinkButtons或ImageButtons 加到TemplateFields里.和BoundField一樣,這些Button被點(diǎn)擊時(shí)會(huì)產(chǎn)生回發(fā),觸發(fā)GridView的RowCommand 事件.當(dāng)添加button到 TemplateField里時(shí),button的CommandArgument 沒(méi)有想使用ButtonFields一樣,被自動(dòng)設(shè)置為row 的index .如果你需要在RowCommand 的event handler里判斷點(diǎn)擊的button所在行的index ,你需要在TemplateField的頁(yè)面代碼里使用以下代碼來(lái)設(shè)置button的CommandArgument 屬性:
asp:Button runat="server" ... CommandArgument='%# CType(Container, GridViewRow).RowIndex %>' />.
總結(jié)
GridView, DetailsView, 和FormView都可以包含Buttons, LinkButtons, 或 ImageButtons.這些button被點(diǎn)擊時(shí),頁(yè)面回發(fā),并激發(fā)FormView 和DetailsView 的ItemCommand 事件,GridView的RowCommand 事件.這些控件都有內(nèi)置的處理普通命令的功能,比如刪除或編輯一條記錄.然而我們一樣可以使用執(zhí)行自定義代碼的button.
為了達(dá)到這個(gè)目的,我們需要為ItemCommand 或 RowCommand 創(chuàng)建一個(gè)event handler .在這個(gè)event handler 里我們首先檢查CommandName 的值來(lái)判斷哪個(gè)button被點(diǎn)擊了,然后執(zhí)行相應(yīng)的自定義代碼.在本指南里我們看到了如何使用button和ButtonField來(lái)停止使用指定supplier 的所有產(chǎn)品,和提高或降低特定product 的10%的價(jià)格.
祝編程快樂(lè)!
作者簡(jiǎn)介
Scott Mitchell,著有六本ASP/ASP.NET方面的書(shū),是4GuysFromRolla.com的創(chuàng)始人,自1998年以來(lái)一直應(yīng)用 微軟Web技術(shù)。Scott是個(gè)獨(dú)立的技術(shù)咨詢顧問(wèn),培訓(xùn)師,作家,最近完成了將由Sams出版社出版的新作,24小時(shí)內(nèi)精通ASP.NET 2.0。他的聯(lián)系電郵為mitchell@4guysfromrolla.com,也可以通過(guò)他的博客http://scottonwriting.net/與他聯(lián)系。
您可能感興趣的文章:- asp.net下gridview 批量刪除的實(shí)現(xiàn)方法
- asp.net gridview 72般絕技
- asp.net gridview代碼綁定
- asp.net GridView控件中模板列CheckBox全選、反選、取消
- asp.net GridView 刪除時(shí)彈出確認(rèn)對(duì)話框(包括內(nèi)容提示)
- Asp.net GridView使用大全(分頁(yè)實(shí)現(xiàn))
- 在ASP.NET 2.0中操作數(shù)據(jù)之十:使用 GridView和DetailView實(shí)現(xiàn)的主/從報(bào)表
- 在ASP.NET 2.0中操作數(shù)據(jù)之十二:在GridView控件中使用TemplateField
- 在ASP.NET 2.0中操作數(shù)據(jù)之十五:在GridView的頁(yè)腳中顯示統(tǒng)計(jì)信息
- 在ASP.NET 2.0中操作數(shù)據(jù)之四十九:為GridView控件添加RadioButton
- 在ASP.NET 2.0中操作數(shù)據(jù)之五十:為GridView控件添加Checkbox
- 在ASP.NET 2.0中操作數(shù)據(jù)之五十一:從GridView的頁(yè)腳插入新記錄