新增 GridView 的選項按鈕欄 (C#)

作者 :Scott Mitchell

下載 PDF

本教學課程將探討如何將單選按鈕數據行新增至 GridView 控件,為使用者提供更直覺的方式,以選取 GridView 的單一數據列。

簡介

GridView 控件提供大量的內建功能。 其中包含數個不同的欄位,用於顯示文字、影像、超連結和按鈕。 它支援範本以進行進一步自定義。 您可以按幾下滑鼠,讓 GridView 能夠透過按鈕選取每個資料列,或啟用編輯或刪除功能。 儘管已提供許多功能,但有時候需要新增其他不支援的功能。 在本教學課程和下兩個教學課程中,我們將探討如何增強 GridView 的功能,以包含其他功能。

本教學課程和下一個著重於增強數據列選取程式。 如使用 可選取的主要 GridView 搭配詳細數據檢視進行檢查,我們可以將 CommandField 新增至包含 [選取] 按鈕的 GridView。 按兩下之後,回傳就會發生,且 GridView 的 SelectedIndex 屬性會更新為按下 [選取] 按鈕之數據列的索引。 在 [ 使用可選取的主要 GridView 搭配詳細數據檢視] 教學課程中,我們已瞭解如何使用這項功能來顯示所選 GridView 數據列的詳細數據。

雖然 [選取] 按鈕在許多情況下運作,但可能不適用於其他人。 除了使用按鈕,其他兩個使用者介面元素通常用於選取:單選按鈕和複選框。 我們可以增強 GridView,而不是選取按鈕,每個數據列都包含單選按鈕或複選框。 在使用者只能選取其中一個 GridView 記錄的情況下,單選按鈕可能會優先於 [選取] 按鈕。 在使用者可能會選取多個記錄的情況下,例如在 Web 型電子郵件應用程式中,使用者可能會想要選取多個訊息來刪除複選框提供無法從 [選取] 按鈕或單選按鈕使用者介面取得的功能。

本教學課程將探討如何將單選按鈕的數據行新增至 GridView。 後續教學課程會探索使用複選框。

步驟 1:建立增強 GridView 網頁

在開始增強 GridView 以包含單選按鈕的數據行之前,讓我們先花一點時間在網站專案中建立 ASP.NET 頁面,我們將在本教學課程和下兩個教學課程中建立所需的頁面。 首先,新增名為 EnhancedGridView的新資料夾。 接下來,將下列 ASP.NET 頁面新增至該資料夾,請務必讓每個頁面與主版頁面產生 Site.master 關聯:

  • Default.aspx
  • RadioButtonField.aspx
  • CheckBoxField.aspx
  • InsertThroughFooter.aspx

為 SqlDataSource-Related 教學課程新增 ASP.NET 頁面

圖 1:為 SqlDataSource-Related 教學課程新增 ASP.NET 頁面

就像在其他資料夾中一樣, Default.aspx 資料夾中 EnhancedGridView 的 將會列出其區段中的教學課程。 回想一下, SectionLevelTutorialListing.ascx 使用者控件會提供這項功能。 因此,將這個使用者控制件Default.aspx從 方案總管 拖曳至頁面的設計檢視,將它新增至 。

將 SectionLevelTutorialListing.ascx 使用者控件新增至 Default.aspx

圖 2:新增 SectionLevelTutorialListing.ascx 使用者控件以 Default.aspx (按兩下以檢視完整大小的影像)

最後,將這四個頁面新增為檔案的專案 Web.sitemap 。 具體而言,請在使用 SqlDataSource 控件 <siteMapNode>之後新增下列標記:

<siteMapNode 
    title="Enhancing the GridView" 
    url="~/EnhancedGridView/Default.aspx" 
    description="Augment the user experience of the GridView control.">
    <siteMapNode 
        url="~/EnhancedGridView/RadioButtonField.aspx" 
        title="Selection via a Radio Button Column" 
        description="Explore how to add a column of radio buttons in the GridView." />
    <siteMapNode 
        url="~/EnhancedGridView/CheckBoxField.aspx" 
        title="Selection via a Checkbox Column" 
        description="Select multiple records in the GridView by using a column of 
            checkboxes." />
    <siteMapNode 
        url="~/EnhancedGridView/InsertThroughFooter.aspx" 
        title="Add New Records through the Footer" 
        description="Learn how to allow users to add new records through the 
            GridView's footer." />
</siteMapNode>

更新 Web.sitemap之後,請花點時間透過瀏覽器檢視教學課程網站。 左側功能表現在包含編輯、插入和刪除教學課程的專案。

網站地圖現在包含增強 GridView 教學課程的專案

圖 3:網站地圖現在包含增強 GridView 教學課程的專案

步驟 2:在 GridView 中顯示供應商

在本教學課程中,讓我們建置一個 GridView 來列出美國供應商,每個 GridView 數據列都會提供單選按鈕。 透過單選按鈕選取供應商之後,使用者可以按下按鈕來檢視供應商的產品。 雖然此工作可能聽起來很簡單,但有一些細微之處可讓它特別棘手。 在我們深入探討這些細微之處之前,讓我們先取得列出供應商的 GridView。

首先,RadioButtonField.aspx從 [工具箱] 將 GridView 拖曳至 Designer,以開啟資料夾中的頁面EnhancedGridView。 將 GridView 設定 IDSuppliers ,然後從其智慧標記選擇建立新的數據源。 具體而言,建立名為 SuppliersDataSource 的 ObjectDataSource,從 SuppliersBLL 物件提取其數據。

建立名為 SuppliersDataSource 的新 ObjectDataSource

圖 4:建立名為 SuppliersDataSource 的新 ObjectDataSource (按兩下即可檢視全大小影像)

[設定數據源 - SuppliersDataSource] 視窗的螢幕快照,其中已選取 Business 物件 SuppliersBLL,並醒目提示 [下一步] 按鈕。

圖 5:將 ObjectDataSource 設定為使用 SuppliersBLL 類別 (按兩下即可檢視完整大小的影像)

因為我們只想在美國列出這些供應商,請 GetSuppliersByCountry(country) 從 [選取] 索引標籤中的下拉式清單中選擇 方法。

[設定數據源 - 供貨商][數據源] 視窗的螢幕快照,其中已開啟 [選取] 索引標籤。已選取 GetSupplierByCountry 方法選項,並醒目提示 [下一步] 按鈕。

圖 6:將 ObjectDataSource 設定為使用 SuppliersBLL 類別 (按兩下即可檢視完整大小的影像)

從 [更新] 索引標籤中,選取 [無) ] 選項 (,然後按 [下一步]。

[設定數據源 - SuppliersDataSource] 視窗的螢幕快照,其中已開啟 [更新] 索引卷標。已選取方法選項 ([無) ],並醒目提示 [下一步] 按鈕。

圖 7:將 ObjectDataSource 設定為使用 SuppliersBLL 類別 (按兩下即可檢視完整大小的影像)

GetSuppliersByCountry(country)由於 方法接受 參數,[設定數據源精靈] 會提示我們輸入該參數的來源。 若要 ( 美國指定硬式編碼值,在此範例中) ,請將 [參數來源] 下拉式清單保留為 [無],然後在文本框中輸入預設值。 按一下 [完成] 以完成精靈。

使用美國作為國家/地區參數的預設值

圖 8:使用美國作為參數的 country 預設值 (按兩下即可檢視完整大小的影像)

完成精靈之後,GridView 會包含每個供應商數據欄位的 BoundField。 拿掉 、 City和 BoundFields,CompanyName並將 BoundFields HeaderText 屬性重新命名CompanyNameCountry Supplier。 執行此動作之後,GridView 和 ObjectDataSource 宣告式語法看起來應該如下所示。

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
    <SelectParameters>
        <asp:Parameter DefaultValue="USA" Name="country" Type="String" />
    </SelectParameters>
</asp:ObjectDataSource>

在本教學課程中,讓我們允許使用者在與供應商清單相同的頁面上,或在不同的頁面上檢視選取的供應商產品。 若要容納這一點,請將兩個 Button Web 控件新增至頁面。 我已將這兩個按鈕的 設定 IDListProductsSendToProducts,並了解 ListProducts 單擊回傳時會發生,而選取的供應商產品將會列在同一個頁面上,但按下時 SendToProducts ,使用者將會被另一個頁面列出產品。

圖 9 顯示 Suppliers 透過瀏覽器檢視時,GridView 和兩個 Button Web 控件。

美國那些供應商的名稱、城市和國家/地區資訊已列出

圖 9:美國供應商的名稱、城市和國家/地區資訊已列出 (按兩下即可檢視完整大小的影像)

步驟 3:新增單選按鈕的數據行

Suppliers此時,GridView 有三個 BoundFields 顯示美國每個供應商的公司名稱、城市和國家/地區。 不過,它仍然缺少單選按鈕的數據行。 可惜的是,GridView 不包含內建 RadioButtonField,否則我們可以將它新增至方格並完成。 相反地,我們可以新增TemplateField並將其設定 ItemTemplate 為轉譯單選按鈕,進而產生每個 GridView 資料列的單選按鈕。

一開始,我們可能會假設想要的使用者介面可以藉由將 RadioButton Web 控件新增至 TemplateField 的 來 ItemTemplate 實作。 雖然這確實會將單一單選按鈕新增至 GridView 的每個數據列,但單選按鈕無法分組,因此不會互斥。 也就是說,終端使用者可以從 GridView 同時選取多個單選按鈕。

雖然使用 RadioButton Web 控制件的 TemplateField 不提供我們需要的功能,但讓我們實作此方法,因為值得檢查為何未分組產生的單選按鈕。 首先,將TemplateField新增至供貨商 GridView,使其成為最左邊的欄位。 接下來,從 GridView 智慧標記按兩下 [編輯範本] 連結,然後將 RadioButton Web 控件從 [工具箱] 拖曳到 TemplateField s ItemTemplate (請參閱圖 10) 。 將 RadioButton 的 ID 屬性設定為 RowSelector ,並將 GroupName 屬性設定為 SuppliersGroup

將 RadioButton Web 控制項新增至 ItemTemplate

圖 10:將 RadioButton Web 控件新增至 ItemTemplate (按兩下即可檢視完整大小的影像)

透過 Designer 進行這些新增之後,您的 GridView 標記看起來應該如下所示:

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:RadioButton ID="RowSelector" runat="server" 
                    GroupName="SuppliersGroup" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CompanyName" HeaderText="Supplier" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
    </Columns>
</asp:GridView>

RadioButton s GroupName 屬性 是用來群組一系列單選按鈕的內容。 所有具有相同 GroupName 值的 RadioButton 控制件都會被視為分組;一次只能從群組中選取一個單選按鈕。 屬性 GroupName 會指定轉譯單選按鈕 s name 屬性的值。 瀏覽器會檢查單選按鈕 name 屬性,以判斷單選按鈕群組。

將 RadioButton Web 控制項新增至 ItemTemplate時,請瀏覽此頁面,並瀏覽瀏覽器,然後按兩下方格數據列中的單選按鈕。 請注意單選按鈕的分組方式,讓您能夠選取所有數據列,如圖 11 所示。

GridView 單選按鈕未分組

圖 11:GridView 單選按鈕未分組, (按兩下即可檢視完整大小的影像)

單選按鈕未分組的原因是因為其轉譯 name 的屬性不同,即使具有相同的屬性設定也一樣 GroupName 。 若要查看這些差異,請從瀏覽器執行檢視/來源,並檢查單選按鈕標記:

<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup" 
    type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector" 
    name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup" 
    type="radio" value="RowSelector" />

name請注意 和 id 屬性不是 屬性視窗 中指定的確切值,但前面會加上一些其他ID值。 新增至轉譯id前方和name屬性的其他ID值是ID父系控件 GridViewRow sID、GridView sID、Content 控件和IDWeb Form s 的單選按鈕的 sID。 系統會新增這些 ID ,讓 GridView 中的每個轉譯 Web 控件都有唯 id 一的值 name

每個轉譯的控件都需要不同的 nameid 因為這是瀏覽器唯一識別用戶端上每個控件的方式,以及它如何識別網頁伺服器在回傳時發生的動作或變更。 例如,假設每當 RadioButton 核取狀態變更時,我們想要執行一些伺服器端程序代碼。 我們可以藉由將 RadioButton 的 AutoPostBack 屬性設定為 true ,併為事件建立事件處理程式 CheckChanged 來完成這項作業。 不過,如果所有單選按鈕的轉 name 譯和 id 值都相同,在回傳時,我們無法判斷所按下的特定 RadioButton。

其簡短在於,我們無法使用 RadioButton Web 控件在 GridView 中建立單選按鈕的數據行。 相反地,我們必須使用相反的原型技術,以確保適當的標記會插入每個 GridView 數據列。

注意

就像 RadioButton Web 控制件一樣,新增至範本時,單選按鈕 HTML 控制件會包含唯 name 一屬性,使方格中的單選按鈕取消分組。 如果您不熟悉 HTML 控件,請放心忽略此附注,因為很少使用 HTML 控件,特別是在 ASP.NET 2.0 中。 但如果您有興趣深入瞭解,請參閱 K. Scott Allen 部落格文章 Web 控件和 HTML 控制件

使用常值控件插入單選按鈕標記

為了正確地將 GridView 中的所有單選按鈕分組,我們必須手動將單選按鈕標記插入 ItemTemplate。 每個單選按鈕都需要相同的 name 屬性,但應該有唯 id 一的屬性 (,以防我們想要透過用戶端腳本) 存取單選按鈕。 當使用者選取單選按鈕並回傳頁面之後,瀏覽器會傳回所選單選按鈕 s value 屬性的值。 因此,每個單選按鈕都需要唯 value 一的屬性。 最後,在回傳時,我們必須確定將 checked 屬性新增至選取的單選按鈕,否則在用戶進行選取和回傳之後,單選按鈕會返回其默認狀態, (所有未選取) 。

有兩種方法可用來將低階標記插入範本中。 其中一個是混合標記和呼叫格式化程序代碼後置類別中定義的方法。 這項技術最初是在 GridView 控件教學課程中使用 TemplateFields 所討論。 在我們的案例中,它看起來可能類似:

<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>' 
    name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />

在這裡,和 GetRadioButtonValue 是程式代碼後置類別中定義的方法,GetUniqueRadioButton會針對每個單選按鈕傳回適當的 idvalue 屬性值。 此方法適用於指派 idvalue 屬性,但需要指定 checked 屬性值時會很短,因為只有在數據第一次系結至 GridView 時,才會執行數據系結語法。 因此,如果 GridView 已啟用檢視狀態,只有當頁面第一次載入 (或 GridView 明確重新繫結至數據源時,才會觸發格式化方法) ,因此不會在回傳時呼叫設定 checked 屬性的函式。 這是相當細微的問題,而且比本文範圍還小一點,因此我會將其留在此處。 不過,建議您嘗試使用上述方法,並逐一處理到您將卡住的點。 雖然這類練習不會讓您更接近工作版本,但它有助於進一步瞭解 GridView 和數據系結生命週期。

在範本中插入自定義、低階標記以及我們將在本教學課程中使用的方法,另一種方法是將 常值控件 新增至範本。 然後,在 GridView s RowCreatedRowDataBound 事件處理程式中,可以透過程式設計方式存取常值控件, Text 並將其 屬性設定為要發出的標記。

從 TemplateField 移除 ItemTemplateRadioButton 開始,將它取代為常值控件。 將常值控制項 ID 設定為 RadioButtonMarkup

將常值控件新增至 ItemTemplate

圖 12:將常值控件新增至 ItemTemplate (按兩下即可檢視完整大小的影像)

接下來,建立 GridView 事件的 RowCreated 事件處理程式。 不論 RowCreated 數據是否要重新系結至 GridView,每個新增的數據列都會引發一次事件。 這表示即使在從檢視狀態重載數據時,在回傳時仍會引發事件, RowCreated 這也是我們使用事件的原因,而不是 RowDataBound (,只有在數據明確系結至數據 Web 控件時才會引發) 。

在此事件處理程式中,我們只想要在處理數據列時繼續進行。 針對每個數據列,我們想要以程序設計方式參考 Literal 控件, RadioButtonMarkup 並將其 屬性設定 Text 為要發出的標記。 如下列程式代碼所示,發出的標記會建立單選按鈕,其name屬性設定為 ,其id屬性設定SuppliersGroupRowSelectorX為 ,其中 X 是 GridView 數據列的索引,而其value屬性設定為 GridView 數據列的索引。

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // Output the markup except for the "checked" attribute
        output.Text = string.Format(
            @"<input type="radio" name="SuppliersGroup" " +
            @"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex);
    }
}

選取 GridView 數據列併發生回傳時,我們對所選供應商的感興趣 SupplierID 。 因此,您可能會認為每個單選按鈕的值應該是實際的 SupplierID (,而不是 GridView 資料列) 的索引。 雖然在某些情況下可能正常運作,但以盲目方式接受和處理 SupplierID會是安全性風險。 例如,我們的 GridView 只會列出美國那些供應商。 不過,如果 SupplierID 直接從單選按鈕傳遞 ,那麼要阻止錯誤的使用者操作 SupplierID 回傳時傳回的值呢? 藉由使用數據列索引做為 value,然後 SupplierIDDataKeys 集合取得 回傳,我們可以確保使用者只使用其中一個與其中一個 SupplierID GridView 數據列相關聯的值。

新增此事件處理程式程式代碼之後,請花一分鐘的時間在瀏覽器中測試頁面。 首先,請注意,一次只能選取方格中的一個單選按鈕。 不過,選取單選按鈕並按兩下其中一個按鈕時,就會發生回傳,而單選按鈕會全部還原為其初始狀態 (也就是說,在回傳時,不會再選取選取的單選按鈕) 。 若要修正此問題,我們需要增強 RowCreated 事件處理程式,以便檢查從回傳傳送的選取單選按鈕索引,並將 屬性新增 checked="checked" 至數據列索引相符專案的發出標記。

發生回傳時,瀏覽器會傳回 name 所選單選按鈕的 和 value 。 您可以使用 以程式設計方式擷取 Request.Form["name"]值。 屬性Request.Form提供NameValueCollection代表表單變數的 。 表單變數是網頁中表單域的名稱和值,每當傳回時,網頁瀏覽器就會傳回。 因為 GridView 中單選按鈕的轉 name 譯屬性是 SuppliersGroup,所以當網頁回傳時,瀏覽器會將 SuppliersGroup=valueOfSelectedRadioButton 傳回網頁伺服器 (,以及其他窗體字段) 。 然後,您可以使用下列方式從 Request.Form 屬性存取這項資訊: Request.Form["SuppliersGroup"]

由於我們不僅需要在事件處理程式中 RowCreated 判斷選取的單選按鈕索引,還需要在 Button Web 控件的事件處理程式中 Click ,將屬性新增至程式碼後置類別,以傳回如果未選取任何單選按鈕,而且選取其中一個 SuppliersSelectedIndex 單選按鈕,則會傳回 -1 選取的索引。

private int SuppliersSelectedIndex
{
    get
    {
        if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
            return -1;
        else
            return Convert.ToInt32(Request.Form["SuppliersGroup"]);
    }
}

新增這個屬性后,我們知道在等於 e.Row.RowIndexSuppliersSelectedIndex,在事件處理程式中RowCreated加入checked="checked"標記。 更新事件處理程式以包含此邏輯:

protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Grab a reference to the Literal control
        Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
        // Output the markup except for the "checked" attribute
        output.Text = string.Format(
            @"<input type="radio" name="SuppliersGroup" " +
            @"id="RowSelector{0}" value="{0}"", e.Row.RowIndex);
        // See if we need to add the "checked" attribute
        if (SuppliersSelectedIndex == e.Row.RowIndex)
            output.Text += @" checked="checked"";
        // Add the closing tag
        output.Text += " />";
    }
}

透過這項變更,選取的單選按鈕會在回傳之後保持選取狀態。 既然我們可以指定選取哪個單選按鈕,我們可以變更行為,以便在第一次瀏覽頁面時,已選取第一個 GridView 數據列的單選按鈕 (,而不是預設未選取任何單選按鈕,也就是目前的行為) 。 若要默認選取第一個單選按鈕,只要將 if (SuppliersSelectedIndex == e.Row.RowIndex) 語句變更為下列專案: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))

此時,我們已將分組單選按鈕的數據行新增至 GridView,以允許跨回傳選取並記住單一 GridView 數據列。 後續步驟是顯示所選供應商所提供的產品。 在步驟 4 中,我們將瞭解如何將使用者重新導向至另一個頁面,並沿著選取 SupplierID的 傳送。 在步驟 5 中,我們將瞭解如何在相同頁面上的 GridView 中顯示選取的供應商產品。

注意

我們可以建立自定義 DataControlField 類別來轉譯適當的使用者介面和功能,而不是使用TemplateField (這個冗長的步驟 3) 。 類別DataControlField是 BoundField、CheckBoxField、TemplateField 和其他內建 GridView 和 DetailsView 欄位衍生的來源基類。 建立自定義 DataControlField 類別表示只要使用宣告式語法即可新增單選按鈕的數據行,而且也會讓其他網頁和其他 Web 應用程式上的功能複寫變得相當容易。

不過,如果您曾經在 ASP.NET 中建立自定義、編譯的控件,您知道這麼做需要相當多的手寫,並攜帶一些必須謹慎處理的細微和邊緣案例。 因此,我們將暫時將單選按鈕數據行實作為自定義 DataControlField 類別,並繼續使用TemplateField選項。 或許我們有機會在未來的教學課程中探索建立、使用及部署自定義 DataControlField 類別!

步驟 4:在個別頁面中顯示選取的供應商產品

用戶選取 GridView 數據列之後,我們需要顯示選取的供應商產品。 在某些情況下,我們可能會想要在另一個頁面中顯示這些產品,而在其他頁面中,我們可能會想要在同一個頁面中執行。 讓我們先檢查如何在個別頁面中顯示產品;在步驟 5 中,我們將探討如何將 GridView 新增至 RadioButtonField.aspx 以顯示所選供應商的產品。

頁面和 SendToProducts目前ListProducts有兩個按鈕 Web 控制件。 SendToProducts按下 [按鈕] 時,我們想要將使用者傳送至 ~/Filtering/ProductsForSupplierDetails.aspx。 此頁面是在 [跨兩頁篩選的主要/詳細數據篩選] 教學課程中建立,並顯示透過名為 SupplierID的查詢字串字段傳遞之供應商SupplierID的產品。

若要提供這項功能,請建立 SendToProducts Button s Click 事件的事件處理程式。 在步驟 3 中,我們新增 SuppliersSelectedIndex 了 屬性,其會傳回已選取單選按鈕之數據列的索引。 您可以從 GridView 集合擷取對應的 SupplierID ,然後使用者就可以使用 Response.Redirect("url")傳送至 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierIDDataKeys

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
    int supplierID = 
        Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
    Response.Redirect(
        "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
        + supplierID);
    }
}

只要已從 GridView 選取其中一個單選按鈕,此程式代碼就非常正常運作。 如果一開始,GridView 並未選取任何單選按鈕,而使用者按下SendToProducts按鈕將會是 -1SuppliersSelectedIndex這會導致擲回例外狀況,因為 -1 超出集合的DataKeys索引範圍。 不過,如果您決定如步驟 3 中所討論更新 RowCreated 事件處理程式,因此一開始選取 GridView 中的第一個單選按鈕,則這不是問題。

若要容納 SuppliersSelectedIndex 的值 -1,請將標籤 Web 控件新增至 GridView 上方的頁面。 將其 ID 屬性設定為 ChooseSupplierMsg、其 CssClass 屬性設定為 Warning、將其 EnableViewStateVisible 屬性設定 false為,並將其 Text 屬性設定為 [請從方格中選擇供貨商]。 CSS 類別 Warning 會以紅色、斜體、粗體、大型字型顯示文字,並在 中 Styles.css定義。 藉由將 EnableViewStateVisible 屬性設定為 false,除了控件 Visible 屬性以程式設計方式設定 true為的回傳之外,不會轉譯 Label。

在 GridView 上方新增標籤 Web 控件

圖 13:在 GridView 上方新增標籤 Web 控件 (按兩下即可檢視全大小影像)

接下來,如果 小於零,請增強 Click 事件處理程式以顯示 ChooseSupplierMsg Label SuppliersSelectedIndex ,否則會將使用者重新導向至 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID

protected void SendToProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
        ChooseSupplierMsg.Visible = true;
    else
    {
        // Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
        int supplierID = 
            Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
        Response.Redirect(
            "~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" 
            + supplierID);
    }
}

瀏覽瀏覽器中的頁面,然後按下 SendToProducts 按鈕,再從 GridView 選取供應商。 如圖 14 所示,這會顯示標籤 ChooseSupplierMsg 。 接下來,選取供應商並按下 SendToProducts 按鈕。 這會讓您前往一個頁面,其中列出所選供應商所提供的產品。 圖 15 顯示 ProductsForSupplierDetails.aspx 選取 Bigfoot 一般工廠供應商時的頁面。

如果未選取供應商,則會顯示 ChooseSupplierMsg 標籤

圖 14ChooseSupplierMsg 如果未選取任何供應商 (,按兩下 即可檢視全大小影像)

選取的供應商產品會顯示在ProductsForSupplierDetails.aspx

圖 15:選取的供應商產品會顯示在 ProductsForSupplierDetails.aspx (按兩下即可檢視全大小的影像)

步驟 5:在相同頁面上顯示選取的供應商產品

在步驟 4 中,我們已瞭解如何將用戶傳送至另一個網頁,以顯示選取的供應商產品。 或者,選取的供應商產品可以顯示在相同的頁面上。 為了說明這一點,我們將新增另一個 GridView 以顯示 RadioButtonField.aspx 所選供應商的產品。

由於我們只想要讓產品 GridView 在選取供應商之後顯示,因此請在 GridView 底下Suppliers新增 Panel Web 控制件,將其設定為 ,並將其 Visible 屬性設定IDProductsBySupplierPanelfalse。 在 [面板] 中,新增 [所選供貨商的產品] 文字,後面接著名為 的 ProductsBySupplierGridView。 從 GridView 智慧標記中,選擇將其系結至名為 ProductsBySupplierDataSource的新 ObjectDataSource。

將 ProductsBySupplier GridView 系結至 New ObjectDataSource

圖 16:將 ProductsBySupplier GridView 系結至新的 ObjectDataSource (按兩下即可檢視大小完整的影像)

接下來,將 ObjectDataSource 設定為使用 ProductsBLL 類別。 由於我們只想要擷取所選供貨商所提供的這些產品,因此請指定 ObjectDataSource 應該叫 GetProductsBySupplierID(supplierID) 用 方法來擷取其數據。 從 [更新]、[插入] 和 [刪除] 索引標籤的下拉式清單中選取 ([無) ]。

將 ObjectDataSource 設定為使用 GetProductsBySupplierID (supplierID) 方法

圖 17:將 ObjectDataSource 設定為使用 GetProductsBySupplierID(supplierID) 方法 (按兩下即可檢視完整大小的影像)

將 Drop-Down 清單 設定為 [UPDATE]、[插入] 和 [刪除] 索引卷標中的 [無) ] (

圖 18:將 [更新]、[插入] 和 [刪除] 索引標籤中的 [Drop-Down 清單] 設定為 ([無) ], (按兩下即可檢視完整大小的映像)

設定 SELECT、UPDATE、INSERT 和 DELETE 索引卷標之後,請按 [下一步]。 GetProductsBySupplierID(supplierID)由於方法需要輸入參數,因此[建立數據源精靈] 會提示我們指定參數值的來源。

我們在這裡有幾個選項可指定參數值的來源。 我們可以使用預設Parameter物件,並以程式設計方式將屬性的值 SuppliersSelectedIndex 指派給 ObjectDataSource 事件處理程式中的Parameter s DefaultValueSelecting 屬性。 如需以程序設計方式將值指派給 ObjectDataSource 參數的重新整理程式,請參閱以 程式設計方式設定 ObjectDataSource 的參數 值教學課程。

或者,我們可以使用 ControlParameter 並參考 Suppliers GridView 屬性SelectedValue, (請參閱圖 19) 。 GridView 的 SelectedValue 屬性會 DataKey 傳回對應至 SelectedIndex 屬性的值。 為了讓這個選項能夠運作,我們需要在按下按鈕時,以程式設計方式將 GridView 的 SelectedIndex 屬性設定為選取的數據 ListProducts 列。 作為新增的優點,藉由設定 SelectedIndex,選取的記錄將會採用 SelectedRowStyle 主題中所 DataWebControls 定義的 (黃色背景) 。

使用 ControlParameter 將 GridView s SelectedValue 指定為參數來源

圖 19:使用 ControlParameter 將 GridView s SelectedValue 指定為參數來源, (按兩下即可檢視完整大小的影像)

完成精靈之後,Visual Studio 會自動新增產品數據欄位的欄位。 拿掉 、 CategoryNameUnitPrice BoundFields,ProductName並將屬性變更HeaderText為 Product、Category 和 Price。 設定 UnitPrice BoundField,使其值格式化為貨幣。 進行這些變更之後,Panel、GridView 和 ObjectDataSource 的宣告式標記看起來應該如下所示:

<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
    <h3>
        Products for the Selected Supplier</h3>
    <p>
        <asp:GridView ID="ProductsBySupplier" runat="server" 
            AutoGenerateColumns="False" DataKeyNames="ProductID"
            DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
            <Columns>
                <asp:BoundField DataField="ProductName" HeaderText="Product" 
                    SortExpression="ProductName" />
                <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                    ReadOnly="True" SortExpression="CategoryName" />
                <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                    HeaderText="Price" HtmlEncode="False" 
                    SortExpression="UnitPrice" />
            </Columns>
        </asp:GridView>
        <asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server" 
            OldValuesParameterFormatString="original_{0}"
            SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
            <SelectParameters>
                <asp:ControlParameter ControlID="Suppliers" Name="supplierID" 
                    PropertyName="SelectedValue" Type="Int32" />
            </SelectParameters>
        </asp:ObjectDataSource>
    </p>
</asp:Panel>

若要完成此練習,我們需要在按下按鈕時,將 GridView 的 SelectedIndex 屬性設定為 SelectedSuppliersIndex ,並將 ProductsBySupplierPanel Panel 屬性Visible設定為 trueListProducts 若要達成此目的,請建立 ListProducts Button Web 控件事件的 Click 事件處理程式,並新增下列程式代碼:

protected void ListProducts_Click(object sender, EventArgs e)
{
    // make sure one of the radio buttons has been selected
    if (SuppliersSelectedIndex < 0)
    {
        ChooseSupplierMsg.Visible = true;
        ProductsBySupplierPanel.Visible = false;
    }
    else
    {
        // Set the GridView's SelectedIndex
        Suppliers.SelectedIndex = SuppliersSelectedIndex;
        // Show the ProductsBySupplierPanel panel
        ProductsBySupplierPanel.Visible = true;
    }
}

如果尚未從 GridView 選取供應商, ChooseSupplierMsg 則會顯示標籤並 ProductsBySupplierPanel 隱藏面板。 否則,如果已選取供應商,則會顯示 , ProductsBySupplierPanel 並更新 GridView 的 SelectedIndex 屬性。

圖 20 顯示已選取 Bigfoot 在 [頁面顯示產品] 按鈕之後的結果。

Bigfoot Factory 所提供的產品會列在相同的頁面上

圖 20:Bigfoot Factory 所提供的產品會列在相同的頁面上, (按兩下即可檢視大小完整的影像)

摘要

使用可選取的主網格線檢視與詳細數據詳細數據檢視教學課程中所述,您可以使用屬性設定為 true的 CommandFieldShowSelectButton,從 GridView 中選取記錄。 但是 CommandField 會將其按鈕顯示為一般按鈕、連結或影像。 替代的數據列選取使用者介面是在每個 GridView 數據列中提供單選按鈕或複選框。 在本教學課程中,我們檢查了如何新增單選按鈕的數據行。

可惜的是,新增單選按鈕數據行並不如預期般簡單或簡單。 沒有內建的 RadioButtonField 可以在按鈕按兩下時新增,而使用 TemplateField 內的 RadioButton Web 控制件會產生自己的一組問題。 最後,為了提供這類介面,我們必須建立自定義 DataControlField 類別,或嘗試在事件期間 RowCreated 將適當的 HTML 插入 TemplateField。

探索如何新增單選按鈕的數據行,讓我們將注意力轉向新增複選框數據行。 透過複選框列,使用者可以選取一或多個 GridView 資料列,然後在所有選取的數據列上執行一些作業 (,例如從 Web 型電子郵件客戶程式選取一組電子郵件,然後選擇刪除所有選取的電子郵件) 。 在下一個教學課程中,我們將瞭解如何新增這類數據行。

快樂的程序設計!

關於作者

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

特別感謝

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