Scott Mitchell 的ASP.NET 2.0數據教程之二十八:: GridView裏的Button

原文 | 下載本教程中的編碼例子 | 下載本教程的PDF版



導言

一般控件(比如GridView)顯示數據的時候對數據只能讀取,而需要處理數據的功能是非常常見的.典型的情況是爲每行數據添加一個Button, LinkButton, 或ImageButton . 當點擊這些button時,數據會PostBack,執行一些服務器端的代碼. 一條條的編輯或刪除數據是最常見的情況.實際上,編輯和刪除是如此常見,從概述插入、更新和刪除數據 開始, 我們可以看到GridView, DetailsView, 和 FormView可以零代碼的完成這些功能.

除了編輯和刪除button,GridView, DetailsView, and FormView 也可以包含一些執行自定義服務器端代碼的Buttons, LinkButtons, 或 ImageButtons .在這一章我們來看看如何向一個GridView 或 DetailsView 裏添加自定義的button.我們還將創建一個根據supplier進行分頁的頁面.對每個給定的supplier,FormView會顯示它的相關信息,外加一個Button .點擊這個Button 時,所有相關products會被標記爲停止使用.另外,GridView 會列出選定的supplier提供的所有product ,並且每一行會包含“Increase Price”和“Discount Price”兩個Button.這兩個Button用來提高或降低10%的product單價(見圖一).

圖 1: FormView和GridView 都包含了執行自定義行爲的Button

第一步: 添加一個Button 教程頁


在研究如何添加自定義button之前,我們先花一點時間在網站裏創建一些頁,這些頁會在本指南里用到.先添加一個名爲CustomButtons的文件夾,然後添加如下的兩個頁.添加頁的時候確保每頁都選擇了Site.master作爲母板頁.

  • Default.aspx
  • CustomButtons.aspx

圖 2: 添加本指南需要的頁面

象其它文件夾一樣,CustomButtons 文件夾裏的Default.aspx 用來列出教程章節.記得SectionLevelTutorialListing.ascx 這個用戶控件提供了這個功能.因此,從解決方案瀏覽裏將這個用戶控件拖到頁面上.

圖 3: 添加SectionLevelTutorialListing.ascx 用戶控件 到Default.aspx


最後,將這些頁的地址加到 Web.sitemap 的條目裏.在Paging and Sorting <siteMapNode>之後添加下面的標記.

<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後,在瀏覽器裏看一下本教程站點,現在左邊的菜單裏包含了編輯,插入,刪除教程的項.

圖 4:  Site Map包含了添加自定義button教程

第二步: 添加一個列出 Supplier的FormView

我們首先來添加一個列出suppliers的FormView .正如在導言裏討論的那樣,FormView根據supplier分頁,並在GridView顯示supplier 提供的所有product .另外FormView 會包含一個Button .當點擊時,所有相關products會被標記爲停止使用.在我們爲FormView添加自定義button之前,我們首先創建顯示supplier 信息的FormView .


打開CustomButtons文件夾裏的CustomButtons.aspx 頁,從工具箱裏拖一個FormView進來,將FormView的ID設置爲Suppliers.打開FormView的智能標籤,創建一個名爲SuppliersDataSource的ObjectDataSource.

圖 5: 創建一個名爲SuppliersDataSource的ObjectDataSource

選擇SuppliersBLL 類的GetSuppliers()方法配置ObjectDataSource(見圖6).由於這個FormView沒有提供修改supplier 信息的界面,所以在UPDATE 標籤的下拉列表裏選擇None.


圖 6: 使用 SuppliersBLL 類的GetSuppliers() 方法配置數據源



數據源配置完成後,Visual Studio會生成一個InsertItemTemplate,一個EditItemTemplate和一個FormView的ItemTemplate.去掉InsertItemTemplate 和EditItemTemplate ,修改ItemTemplate,讓它只顯示supplier的公司名,電話號碼.最後,在智能標籤裏選中Enable Paging checkbox 或者設置AllowPaging 屬性爲True.完成這些後,你的聲明標記看起來應該和以下差不多:

<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列出當前選定的Supplier的CompanyName and Phone

第三步 : 添加一個GridView,用來列出某個Supplier的所有Product


在添加“Discontinue All Products”Button 前,先在FormView 下面添加一個GridView . 設置ID 爲SuppliersProducts,添加一個名爲SuppliersProductsDataSource的ObjectDataSource .


圖 8: 創建一個名爲SuppliersProductsDataSource的ObjectDataSource



選擇ProductsBLL 類的GetProductsBySupplierID(supplierID)方法配置ObjectDataSource(見圖9).雖然GridView 允許修改product的價格,但是並不使用的GridView自帶的編輯或刪除功能.因此在UPDATE, INSERT, and DELETE 標籤的下拉列表裏都選擇None.


圖 9: 使用ProductsBLL 類的GetProductsBySupplierID(supplierID) 方法配置數據源



由於GetProductsBySupplierID(supplierID)有一個輸入參數,ObjectDataSource嚮導會提示我們配置這個參數.爲了將SupplierID 從FormView傳過來,在參數來源的下來列表裏選擇Control,在ControlID 下拉列表裏選擇Suppliers (在第二步裏創建的FormView 的ID).



圖 10: 指定 supplierID 參數的來源爲Suppliers FormView


完成了ObjectDataSource 嚮導後,GridView 裏的每一行product會包含一個BoundField 和一個CheckBoxField . 我們來精簡一下,只顯示Discontinued CheckBoxField,ProductName 和UnitPrice .我們修改UnitPrice 列的格式爲貨幣. 你的GridView 和SuppliersProductsDataSource  ObjectDataSource的聲明標記看起來應該和下面差不多:


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


現在我們的顯示了一個主/從表,用戶通過在上面的FormView 裏選擇一個supplier ,在下方的GridView 裏就可以看到這個supplier 提供的products.
圖11是在FormView裏選擇Tokyo Traders supplier 的截圖.



圖 11: 在GridView顯示選定的Supplier的產品

第四步: 創建DAL和BLL層的停止使用Supplier的所有Products 的方法



在FormView 添加discontinue button前,我們首先需要在DAL 和BLL 裏添加完成這個功能的方法.這個方法的名字爲DiscontinueAllProductsForSupplier(supplierID). 當點擊FormView的Button 時,我們會調用Business Logic Layer裏的這個方法,並將選定的supplier的SupplierID傳進去.BLL 會繼續調用Data Access Layer的相關方法,這個方法會向數據庫提交一個停止使用選定的supplier的products的UPDATE語句


象在以前的教程裏所做的那樣,我們使用自底向上的方法,首先創建DAL 的方法,然後是BLL ,最後在 ASP.NET page裏實現這個功能.打開App_Code/DAL文件夾裏的Northwind.xsd ,爲ProductsTableAdapter 添加一個新方法(右鍵點擊ProductsTableAdapter ,選擇Add Query).這樣彈出TableAdapter Query 的配置嚮導.首先指定DAL 需要使用的SQL .

圖 12: 使用SQL Statement創建DAL 方法



接着,嚮導會詢問我們創建哪種類型的query .由於DiscontinueAllProductsForSupplier(supplierID)需要更新Products表,爲指定的supplierID 的所有products的Discontinued 字段設置爲1,因此我們需要創建一個更新數據的query .


圖 13: 選擇UPDATE Query的類型


下一個嚮導顯示的窗口提供了TableAdapter的已經存在的UPDATE 語句,它會updates 在Products DataTable定義的所有的字段.用下面的語句替換它:

UPDATE [Products] SET
   Discontinued = 1
WHERE SupplierID = @SupplierID

輸入以上語句後點Next,最後一個嚮導窗口需要輸入該方法的名字—DiscontinueAllProductsForSupplier.完成嚮導後點Finish  button.當你回到DataSet 設計器時你應該可以在ProductsTableAdapter 看到名爲DiscontinueAllProductsForSupplier(@SupplierID)的方法.

圖 14: 爲 DAL 的方法取名爲 DiscontinueAllProductsForSupplier



完成Data Access Layer裏的DiscontinueAllProductsForSupplier(supplierID)方法後,我們下一步的任務是創建Business Logic Layer裏的相應的方法.打開ProductsBLL 類文件,添加以下內容:

public int DiscontinueAllProductsForSupplier(int supplierID)
{
    return Adapter.DiscontinueAllProductsForSupplier(supplierID);
}

這個方法僅僅是調用DAL裏的DiscontinueAllProductsForSupplier(supplierID)方法,並傳遞提供的supplierID  參數.如果有一些業務規則規定僅僅允許在一定的條件下supplier的products 才能被停止使用,那麼這些規則應該寫在這裏(BLL).


注意:和ProductsBLL 類的UpdateProduct重載不一樣,DiscontinueAllProductsForSupplier(supplierID)的簽名不包括DataObjectMethodAttribute 屬性(<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>).這個將DiscontinueAllProductsForSupplier(supplierID) 方法從ObjectDataSource的配置數據源嚮導的UPDATE標籤裏的下拉列表中排除.我之所以忽略這個屬性是因爲我們會在ASP.NET page裏直接通過event handler 調用DiscontinueAllProductsForSupplier(supplierID)方法.

第五步: 爲FormView添加一個“Discontinue All Products” Button

完成了BLL 和 DAL 裏的DiscontinueAllProductsForSupplier(supplierID)方法後,我們來做實現停止使用選定的supplier的所有product的功能最後一步:爲 FormView的 ItemTemplate添加Button .我們將這個Button 添加在supplier的phone number下,Text爲“Discontinue All Products”,ID爲DiscontinueAllProductsForSupplier.你可以通過FormView的智能標籤裏的Edit Templates 來添加這個Button (見圖15),或直接修改代碼.

圖 15: 爲FormView的ItemTemplate添加 “Discontinue All Products” Button

當用戶點擊這個Button 時,頁面會回發,FormView的ItemCommand event被激發.我們可以爲這個事件創建一個event handler ,用來在Button 被點擊時執行自定義代碼.注意,任何時候FormView裏的任何Button, LinkButton, 或 ImageButton被點擊時,ItemCommand 事件都會被激發.這意味着當用戶在FormView裏從一個頁面跳到另一個頁面時,ItemCommand 事件會被激發.當用戶點擊一個支持inserting, updating, 或 deleting的FormView裏的New, Edit, 或 Delete 時,ItemCommand 事件會被激發.

既然無論點擊什麼button時, ItemCommand 都會被激發,那麼在event handler裏我們需要判斷是“Discontinue All Products” Button 被點擊了還是其它的button.爲了達到這個目的,我們可以通過設置Button 的CommandName來識別. 當Button 被點擊後,CommandName 的值被傳到ItemCommand 的event handler,我們通過這個值來判斷被點擊的button是否是“Discontinue All Products” Button.設置“Discontinue All Products” Button的CommandName 爲“DiscontinueProducts”.

最後我們在客戶端增加一個確認框來確保用戶真的想停止使用選擇的supplier的所有product.和我們在爲刪除數據添加客戶端確認 裏看到的一樣,這個可以用JavaScript來完成. 設置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 事件創建event handler . 在這個event handler 裏我們需要首先判斷“Discontinue All Products”Button是否被點擊了.如果是,我們就需要創建一個ProductsBLL 類的實例然後調用DiscontinueAllProductsForSupplier(supplierID)方法,並將FormView裏選定的SupplierID 傳過去.


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 裏當前選定的supplier 的SupplierID 可以通過FormView的 SelectedValue property屬性獲取.SelectedValue 屬性返回FormView裏顯示的記錄的第一個data key的值.FormView的DataKeyNames property在綁定ObjectDataSource 到FormView 時(第二步)會自動的被設置爲SupplierID .

ItemCommand event handler 創建完後,花點時間測試一下這個頁面.瀏覽Cooperativa de Quesos 'Las Cabras' supplier (在我這是FormView 裏的第五個supplier ).這個supplier 提供兩種product, Queso Cabrales and Queso Manchego La Pastora,兩個都沒有停止使用的.

想象一下 Cooperativa de Quesos 'Las Cabras' 歇業了,因此它的產品都要被停止使用.點擊“Discontinue All Products” Button.會彈出一個確認的對話框.

圖 16: Cooperativa de Quesos 'Las Cabras' 供應 兩種有效的產品

如果在確定對話框裏點擊OK,表單提交就會繼續,ormView的ItemCommand 事件會被激發.然後我們創建的event handler會執行,調用DiscontinueAllProductsForSupplier(supplierID)方法,停止使用Queso Cabrales 和 Queso Manchego La Pastora這兩個產品.

如果你禁用了GridView的view state,每次postback時GridView 都會重新綁定,因此這兩種product被停止使用的狀態馬上就能顯示出來(見圖17).而如果沒有禁用GridView的view state,你需要手動再次綁定數據.

圖 17: 點擊 “Discontinue All Products” Button後, Supplier的 Products被更新

第六步: 爲調整Product的價格,在Business Logic Layer 創建一個UpdateProduct



和FormView裏的“Discontinue All Products” Button 一樣,爲了在GridView 裏添加提高或者降低product 的價格的button,我們首先添加Data Access Layer and Business Logic Layer 的方法.由於我們在DAL裏已經有一個更新單個產品記錄的方法,我們可以通過在BLL創建UpdateProduct 的重載方法來實現這個功能.

我們以前的UpdateProduct 包括一些product 字段作爲輸入值,我們可以爲指定的product更新這些字段.我們將做少量修改,傳遞ProductID 和調整單價的百分比.因爲不用再測定當前product 的單價,所以這樣的方法會讓我們在ASP.NET page 的cs文件裏的代碼變的更簡潔.

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


這個方法通過DAL的GetProductByProductID(productID)方法獲取指定product 的信息.它會檢查product的單價是否是空值.如果是,這個價格就不被更改.如果不是,product的UnitPrice 將根據指定的百分比更改(unitPriceAdjustmentPercent)

 

第七步: 在GridView裏添加升價和降價的Button


GridView (和DetailsView)都是字段的集合.除了BoundFields, CheckBoxFields, and TemplateFields這幾個字段外,ASP.NET還包含ButtonField.就象它的名字一樣,ButtonField提供一個Button, LinkButton, 或 ImageButton列.和FormView一樣,點擊GridView 裏的任何一個button— 分頁,編輯或刪除,排序等— 頁面都會回發 ,並激發GridView的RowCommand event.

ButtonField 有一個CommandName 屬性,可以用來指派特定的值給每個Button的CommandName 屬性.象FormView一樣,CommandName 的值用來在RowCommand event handler 裏判斷哪個button被點擊了.

現在我們來爲GridView添加兩個ButtonField,一個的text爲“Price +10%” ,另外一個的text爲“Price -10%”. 點擊GridView的智能標籤裏的Edit Columns link ,在左上的列表裏選擇ButtonField 類,點添加.


圖 18: 爲GridView添加兩個ButtonField

移動這兩個ButtonField 到GridView 的前兩列.分別設置ButtonField的text爲 “Price +10%” and “Price -10%”,CommandName 爲“IncreasePrice” and “DecreasePrice”,.默認情況下,ButtonField 裏的button爲LinkButtons,這個是可通過ButtonField的ButtonType property屬性來修改的.我們將這兩個ButtonField設置爲常規的push button.因此,設置ButtonType 屬性爲Button.圖19顯示了設置完成後的Fields 對話框的樣子.而後面一個圖則爲GridView的頁面代碼.

圖 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>
創建ButtonField完成後,最後一步是爲GridView的RowCommand 事件創建event handler .當“Price +10%”或“Price -10%”button被點擊時,這個event handler需要判斷被點擊的那一行的ProductID ,然後調用ProductsBLL 類的UpdateProduct 方法,並將UnitPrice 的調整折扣和ProductID傳進去.下來的代碼會完成以上工作:


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);
    }
}


爲了判斷被點擊“Price +10%” or “Price -10%” button 的那一行的ProductID ,我們需要用到GridView的DataKeys 集合.這個集合包含了GridView 的行的所有值.由於GridView在綁定到ObjectDataSource 時,DataKeyNames 被Visual Studio設置爲ProductID ,DataKeys(rowIndex).Value 提供了指定rowIndex的ProductID .

ButtonField 會將被點擊的button所在row 的rowIndex 自動傳到e.CommandArgument 參數裏.因此,我們用Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)來獲取被點擊“Price +10%” or “Price -10%” button的行的ProductID .

和“Discontinue All Products” button裏一樣,如果你禁用了GridView的view state屬性,每次postback時GridView 都會重新綁定.如果你這麼做,你需要手動再次綁定.

圖20顯示當瀏覽Grandma Kelly's Homestead提供的product的頁.圖21顯示當Grandma's Boysenberry Spread 的“Price +10%” button 被點擊了兩次和Northwoods Cranberry Sauce的“Price -10%” button被點擊了一次的頁面.

Figure 20: The GridView Includes “Price +10%” and “Price -10%” Buttons

圖 21: 第一和第三個產品的價格通過“Price +10%” and “Price -10%” Buttons更新

注意:GridView (和DetailsView)同樣可以將Buttons,LinkButtons或ImageButtons 加到TemplateFields裏.和BoundField一樣,這些Button被點擊時會產生回發,觸發GridView的RowCommand 事件.當添加button到 TemplateField裏時,button的CommandArgument 沒有想使用ButtonFields一樣,被自動設置爲row 的index .如果你需要在RowCommand 的event handler裏判斷點擊的button所在行的index ,你需要在TemplateField的頁面代碼裏使用以下代碼來設置button的CommandArgument 屬性:
<asp:Button runat="server" ... CommandArgument='<%# CType(Container, GridViewRow).RowIndex %>' />.

總結


GridView, DetailsView, 和FormView都可以包含Buttons, LinkButtons, 或 ImageButtons.這些button被點擊時,頁面回發,並激發FormView 和DetailsView 的ItemCommand 事件,GridView的RowCommand 事件.這些控件都有內置的處理普通命令的功能,比如刪除或編輯一條記錄.然而我們一樣可以使用執行自定義代碼的button.

爲了達到這個目的,我們需要爲ItemCommand 或 RowCommand 創建一個event handler .在這個event handler 裏我們首先檢查CommandName 的值來判斷哪個button被點擊了,然後執行相應的自定義代碼.在本指南里我們看到了如何使用button和ButtonField來停止使用指定supplier 的所有產品,和提高或降低特定product 的10%的價格.


祝編程快樂!

作者簡介

Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。Scott是個獨立的技術諮詢顧問,培訓師,作家,最近完成了將由Sams出版社出版的新作,24小時內精通ASP.NET 2.0。他的聯繫電郵爲[email protected],也可以通過他的博客http://scottonwriting.net/與他聯繫。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章