为 GridView 添加一列单选按钮50
簡介
GridView 控件提供多種內置功能。它含有多個顯示文本、圖像、超鏈接和按鈕的不同字段。它還支持模板的進一步定制。只需輕輕的點擊幾下鼠標,您即可構造 GridView ,使其每行均可使用按鈕進行選擇,或者啟用編輯或刪除功能。盡管它提供了多種功能,但是很多情況下我們仍然需要添加一些附加功能和它不支持的功能。在本教程和接下來的兩篇教程中,我們將探討如何增強 GridView 的功能,使之包含更多的附加功能。
本教程和下一個教程重點探討如何增強選行流程。正如在?使用具有 Details DetailView 功能的可選主 GridView 的主/ 明細報表?中討論的一樣 , 我們可以向GridView 添加CommandField , 該 CommandField 包含一個 Select 按鈕。單擊后緊接著會回傳 , 并且 GridView 的 SelectedIndex 屬性將更新到行索引 , 此行的 Select 按鈕為被點擊的按鈕。在?使用具有 Details DetailView 功能的可選主 GridView 的主/ 明細報表?教程中 , 我們了解了如何使用此功能顯示選定 GridView 行的詳細情況。 ,
盡管 Select 按鈕適用于多種情況,但是它可能并不適用于其它情況。并不經常使用按鈕,而是通常使用其它兩個用戶界面元素來進行選擇:單選按鈕和復選框。我們可添加一個 GridView ,代替 Select 按鈕,從而保證每行均包含一個單選按鈕或者復選框。在用戶僅可選擇 GridView 記錄中的一條記錄的情況下,單選按鈕可能要優于 Select 按鈕。在用戶可選擇多條記錄的情況下(例如基于 web 的電子郵件程序,用戶可能希望選擇刪除多條信息),復選框可提供 Select 按鈕和單選按鈕用戶界面無法提供的功能。
本教程將探討如何向 GridView 添加一列單選按鈕。下個教程還將探討如何使用復選框。 .
步驟1 : 創建增強 GridView 的 Web 頁面
在我們開始增強 GridView 功能 , 使之包含一列單選按鈕之前 , 我們首先花點時間在我們的網站項目中創建本教程和下兩個教程需要的ASP.NET 頁面。首先 , 添加一個名為 EnhancedGridView 的新文件夾。接下來 , 將以下 ASP.NET 頁面添加到該文件夾 , 確保每個頁面與 Site.master 主頁面相關聯 :
- Default.aspx
- RadioButtonField.aspx
- CheckBoxField.aspx
- InsertThroughFooter.aspx
圖1 :?為 SqlDataSourc 相關教程添加 ASP.NET 頁
與其它文件夾一樣 ,EnhancedGridView 文件夾中的 Default.aspx 頁將列出教程。回想一下 ,SectionLevelTutorialListing.ascx 用戶控件提供本功能。因此 , 請通過從Solution Explorer 中將此 用戶 控件拖放到頁面的 Design 視圖來添加此 用戶 控件。
圖2 :?將SectionLevelTutorialListing.ascx 用戶控件添加至 Default.aspx
最后 , 將這四個頁面按條目添加到 Web.sitemap 文件中。具體地說 , 在 “Using the SqlDataSource Control” <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 后 , 花點時間用瀏覽器查看一下教程網站。現在,左邊的菜單包含用于編輯、插入和刪除教程的各項。
圖3 :?現在 , 網站地圖中包含了增強 GridView 教程的條目
步驟2 : 在GridView 中顯示供應商
在本教程中 , 我們將創建一個列出美國供應商的 GridView , 每個 GridView 行均提供了一個單選按鈕。在使用單選按鈕選擇一個供應商之后,用戶可以單擊按鈕查看供應商的產品。盡管此任務似乎微不足道,但是存在一些微妙之處,使它變得非常棘手。 在我們深入研究這些微妙之處之前,我們首先獲得一個列出供應商的 GridView 。
首先 , 通過將GridView 從工具箱拖放到設計器中 , 在 EnhancedGridView 文件夾中打開RadioButtonField.aspx 頁。將 GridView 的 ID 設置為 Suppliers , 從其智能標記中 , 選擇創建新數據源。具體地說 , 創建一個名為SuppliersDataSource 的 ObjectDataSource ,ObjectDataSource 從 SuppliersBLL 對象提取數據。
圖4 :?創建一個名稱為 SuppliersDataSource 的新的 ObjectDataSource
?
圖5 :?配置 ObjectDataSource , 使之使用 SuppliersBLL 類
由于我們只希望列出美國的供應商 , 因此 , 請從SELECT 選項卡的下拉列表中選擇 GetSuppliersByCountry(country) 方法。
圖6 :?配置 ObjectDataSource , 使之使用 SuppliersBLL 類
從UPDATE 選項卡選擇 “(None)” 選項 , 并單擊Next 。
圖7 :?配置 ObjectDataSource , 使之使用 SuppliersBLL 類
由于GetSuppliersByCountry(country) 方法可接受參數 ,Configure Data Source 向導將提示我們輸入這個參數的源。要想指定固定值 ( 此例中為 “USA” ), 請保留 Parameter source 下拉列表的None 設置 , 并在文本框中輸入默認值。單擊 Finish 完成向導。
圖8 :?使用 “USA” 作為國家參數的默認值
完成向導之后 ,GridView 將為每個供應商數據字段包含一個BoundField 。刪除 CompanyName 、City 和 Country BoundField 之外的所有 BoundField , 并把 CompanyName BoundFields HeaderText 屬性重命名為 “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>
在本教程中 , 我們允許用戶在供應商列表或者其它頁面上查看選定供應商的產品。要達到這一目的,請在頁面上添加兩個 Web 按鈕控件。我已經將這兩個Web 按鈕 的 ID 設置為 ListProducts 和SendToProducts , 我的想法是:單擊 ListProducts 時將出現回傳 , 并且選定供應商的產品將被列在同一個頁面上 , 但是 , 單擊 SendToProduct 時 , 用戶將被轉到其它列出產品的頁面上。
圖9 顯示通過瀏覽器查看頁面時 , 頁面上顯示了 Suppliers GridView 和兩個Web 按鈕 控件。
圖9 :?頁面上列出了美國供應商的名稱、城市和國家信息
步驟3 : 添加一列單選按鈕
此時 ,Suppliers GridView 有三個 BoundField , 分別顯示美國供應商的公司名稱、城市和國家。但是 , 它還缺少一列單選按鈕。遺憾的是 ,GridView 不包含內置的 RadioButtonField , 否則我們可以向網格中添加 RadioButtonField , 并完成這項工作。或者 , 我們可以添加一個TemplateField , 并將其 ItemTemplate 配置為提供單選按鈕 , 從而為每個GridView 行添加單選按鈕。
最初 , 我們可能假定所需的用戶界面可以通過向TemplateField 的 ItemTemplate 添加一個 RadioButton Web 控件來實現。盡管這樣實際上會向 GridView 的每一行都添加一個單選按鈕,這些單選按鈕不能分組,因此并不互相排斥。也就是說,最終用戶可以同時從 GridView 選擇多個單選按鈕。
盡管使用RadioButton Web 控件的TemplateField 不提供我們所需的功能 , 我們還是要采用這種方式 , 因為它可以檢查造成單選按鈕不被分組的原因 , 因此是值得的。首先 , 向Suppliers GridView 添加一個 TemplateField , 使其成為最左邊的字段。接下來 , 從GridView 的智能標記單擊 Edit Templates 鏈接 , 并將RadioButton Web 控件從文本框拖放到 TemplateField 的 ItemTemplate ( 見圖10 )。 將RadioButton 的 ID 屬性設置為 RowSelector , 將 GroupName 屬性設置為SuppliersGroup 。
圖10 :?向 ItemTemplate 添加 RadioButton Web 控件
使用設計器完成添加操作之后 ,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 的?GroupName 屬性?用于對一系列單選按鈕進行分組。具有同一GroupName 值的所有 RadioButton 控件被認為已被分組 ; 每次只能從一個組中選擇一個單選按鈕。 GroupName 屬性用于指定呈現的單選按鈕的名稱屬性值。瀏覽器檢查單選按鈕的名稱屬性值,確定單選按鈕的分組。
將RadioButton Web 控件添加到 ItemTemplate 之后 , 請通過瀏覽器訪問此頁面 , 并單擊網格行中的單選按鈕。請注意單選按鈕并未分組,因此可選擇所有的行,如圖 11 所示。
圖11 :GridView 的單選按鈕并未分組
單選按鈕并未分組的原因是它們呈現的名稱屬性值不同 , 盡管它們具有相同的GroupName 屬性設置。要查看這些區別,在瀏覽器中選擇 View/Source ,并檢查單選按鈕標記:
<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"?/>
請注意 , 名稱和ID 屬性的值與 Properties 窗口中指定的值并不完全相同 , 而是預置了一些其它 ID 值。添加到呈現的 ID 和名稱屬性前頭的附加 ID 值是單選按鈕父控件的 ID – GridViewRows 的 ID 、GridView 的 ID 、Content 控件的 ID 和Web Form 的 ID 。添加這些 ID 是為了保證 GridView 中每個呈現的 Web 控件具有唯一的 ID 值和名稱值。
每個呈現的控件需要具有不同的名稱和ID , 因為這是瀏覽器在客戶端區分每個控件以及在回傳時確定網絡服務器發生什么操作或者更改的唯一途徑。例如,我們假設:一旦 RadioButton 的選定狀態發生變更,希望運行某些服務器端代碼。我們可以通過將RadioButton 的 AutoPostBack 屬性設置為 True , 并為 CheckChanged 事件創建 Event Handler 來實現這一目標。但是,如果所有單選按鈕呈現的名稱和 ID 值都相同,回傳時我們將無法確定到底單擊了哪個特定的 RadioButton 。
總之 , 我們不能使用RadioButton Web 控件在 GridView 中創建一列單選按鈕。而且 , 我們必須使用相當陳舊的技術保證標記被注入到每個GridView 行。
注意 :?和 RadioButton Web 控件一樣,單選按鈕 HTML 控件在添加到模板時將包含唯一的名稱屬性,保證網格中單選按鈕未進行分組。如果您不熟悉HTML 控件 , 您可以按照您的意愿忽略本提示 , 因為HTML 控件很少使用 , 尤其是在 ASP.NET 2.0 中。但是如果您愿意了解更多內容 , 請參照?K. Scott Allen?的博客日志?Web Controls and HTML Controls?。
使用Literal 控件插入單選按鈕標記
為了能夠將GridView 內的所有單選按鈕正確分組 , 我們需要手工將單選按鈕的標記插入 ItemTemplate 。每個單選按鈕需要相同的名稱屬性,但是,每個單選按鈕應該具有唯一的 ID 屬性(假如我們希望通過客戶端腳本訪問單選按鈕)。在用戶選定單選按鈕,并回傳頁面時,瀏覽器將送回選定單選按鈕的 value 屬性的值。因此,每個單選按鈕需要具有唯一的 value 屬性。最后,我們需要在回傳時確保將 checked 屬性添加到選定的單選按鈕,否則,在用戶完成選擇并回傳時,單選按鈕將返回到它們的默認狀態(全部取消選定)。
可以采用兩種方式將低級標記插入到模板中。第一種方式是組合標記 , 并調用 代碼文件 類中定義的格式化方法。該方法首次提及是?在 GridView控件中使用 TemplateField?教程中。在我們的例子中 , 它可能類似如下 :
<input?type="radio"?id='<%#?GetUniqueRadioButtonID(...)?%>'??????name='SuppliersGroup'?value='<%#?GetRadioButtonValue(...)?%>'?...?/>
此處 ,GetUniqueRadioButton 和 GetRadioButtonValue 為 代碼文件 類中定義的方法 ,它們 返回每個單選按鈕的相應的 ID 和 value 屬性的值。這種方法非常適用于分配id 和 value 值 , 但是在需要指定 checked 屬性值時就不管用了 , 因為數據綁定語法僅當數據首次綁定到GridView 時才執行。因此,如果 GridView 啟用了視圖狀態,格式化方法將僅在首次加載頁面時(或者在 GridView 明確綁定到數據源時)才會觸發,因此,在回傳時不會調用設置 checked 屬性的函數。這是一個非常棘手的問題,并有些超出本文的范圍,所以本文不再討論。但是,我推薦你們嘗試一下使用上述方法,并進行到遇到困難為止。盡管這樣的練習與使用版本還有一段距離,但它仍然會加深您對 GridView 和數據綁定生命周期的理解。
向模板中插入定制的低級標記的另外一種方法 ( 在本教程中使用的方法 ) 是向模板添加?Literal 控件?。然后 ,可以通過 在 GridView 的 RowCreated 或 RowDataBound Event Handler 中編碼來訪問 Literal 控件 , 并將其 Text 屬性設置為要傳輸的標記。
首先 , 從TemplateField 的 ItemTemplat 刪除RadioButton , 并替換為 Literal 控件。將 Literal 控件的 ID 設置為 RadioButtonMarkup 。
圖12 :向 ItemTemplate 添加 Literal 控件
接下來 , 為GridView 的 RowCreated 事件創建Event Handler 。無論數據是否重新綁定到 GridView , 添加每一行時均將觸發 RowCreated 事件。這意味著既使從視圖狀態重新加載數據產生回傳時 , 仍會觸發RowCreated , 這也是我們使用 RowCreated 而不用 RowDataBound 的原因 (RowDataBound 只有在數據明確綁定到 Web 數據 控件時才會觸發 ) 。
在此 Event Handler 中 , 我們希望僅在我們處理數據行時才運行。對于每個數據行來說 , 我們希望通過編碼引用 RadioButtonMarkup Literal 控件 , 并將其 Text 屬性設置為要傳輸的標記。正如下列代碼所示 , 傳輸的標記將創建一個單選按鈕 , 此單選按鈕的名稱屬性設置為 SuppliersGroup ,id 屬性設置為 RowSelectorX?, 其中 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 值造假呢 ? 通過使用行索引值 , 然后在回傳時從DataKeys 集合獲取 SupplierID 值 , 我們可以保證用戶僅使用與某一 GridView 行關聯的 SupplierID 值。
在添加完成此Event Handler 代碼后 , 請花點時間在瀏覽器中測試該頁面。首先,請注意每次只能在網格中選擇一個單選按鈕。但是,當選擇一個單選按鈕,并單擊某個按鈕時,將出現回傳,并且單選按鈕全部恢復到它們的初始值(也就是說,在回傳時,選定的單選按鈕已經不再選定)。要解決這個問題 , 我們需要擴充RowCreated Event Handler , 使其檢查從回傳發送的選定單選按鈕的索引 , 并向傳輸的匹配行索引標記添加checked="checked" 屬性。
出現回傳時,瀏覽器將送回選定單選按鈕的名稱和值。單選按鈕值可以通過編碼使用Request.Form("name") 進行檢索。Request.Form 屬性?提供了一個?NameValueCollection?來代表表格變量。表格變量為 web 頁面上的表格字段的名稱和值,并且在回傳時由 web 瀏覽器發回。由于 GridView 中呈現的單選按鈕的 name 屬性為 SuppliersGroup ,web 頁面回傳時 , 瀏覽器將把 SuppliersGroup=valueOfSelectedRadioButton?回傳到web 服務器 ( 與其它表格字段一起 ) 。然后 , 此信息可從 Request.Form 屬性訪問 , 使用的訪問方式為 : Request.Form("SuppliersGroup")。
由于我們需要不僅在 RowCreated Event Handler 中確定選定單選按鈕索引 , 而且還要在 Web 按鈕控件的 Click Event Handler 確定 ,因此 我們需要向 代碼文件 類添加一個SuppliersSelectedIndex 屬性 , 該屬性在單選按鈕未選定時返回-1 , 在選定某個單選按鈕時返回選定的索引。
private?int?SuppliersSelectedIndex?{?
????get?
????{?
????????if?(string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))?
????????????return?-1;?
????????else?
????????????return?Convert.ToInt32(Request.Form["SuppliersGroup"]);?
????}?
}
添加該屬性之后 , 當SuppliersSelectedIndex 等于e.Row.RowIndex 時 , 我們要在 RowCreated Event Handler 中添加checked="checked" 標記。 更新 Event Handler 使其包含下列邏輯:
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 OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then 。
此時 , 我們已經向GridView 添加了一列分組單選按鈕 , 分組單選按鈕允許選擇單個 GridView 行 , 并在回傳時進行記錄。下一步是顯示選定供應商的產品。在步驟 4 中,我們將了解如何將用戶重定向到其它頁面,發送選定的 SupplierID 。在步驟 5 中,我們將了解如何在相同頁面的 GridView 中顯示選定供應商的產品。
注意 :?我們可以創建一個顯示適當的用戶界面和功能的定制DataControlField 類 , 而不是使用 TemplateField ( 這是稍顯冗長的步驟 3 重點介紹的 ) 。?DataControlField 類?是基類 ,BoundField 、CheckBoxField 、TemplateField 和其它內置 GridView 和 DetailsView 字段均從其派生出來。創建一個定制 DataControlField 類意味著只使用聲明語法就可添加單選按鈕列 , 并且可以方便地在其它web 頁面和其它 web 應用程序上重用此功能。
如果您曾經在 ASP.NET 中創建過定制、編譯控件 , 那么 , 您會知道這個過程需要數量可觀的瑣碎工作 , 以及必須小心處理多個微妙問題和邊緣情況。因此 , 這里我們放棄通過定制 DataControlField 類的方案實施單選按鈕列 , 堅持選擇使用 TemplateField 。可能在后續教程中我們有機會探討創建、使用和部署定制 DataControlField 類。
步驟4 : 在單獨頁面上顯示選定供應商的產品
在用戶選定GridView 行之后 , 我們需要顯示選定供應商的產品。在某些情況下,我們可能希望在單獨的頁面上顯示這些產品,而在另外的一些情況下,我們更希望在同一個頁面上顯示這些產品。我們首先探討如何在單獨頁面上顯示產品;在步驟 5 中,我們將了解向 RadioButtonField.aspx 添加 GridView 來顯示選定供應商的產品。
目前 , 頁面上有兩個Web 按鈕 控件 – ListProducts 和 SendToProducts 。單擊 SendToProducts Button 時 , 我們希望將用戶轉到 ~/Filtering/ProductsForSupplierDetails.aspx 。此頁面是在?跨兩頁面的主/ 明細篩選?教程中創建的,用于顯示其 SupplierID 通過名為 SupplierID 的 querystring 字段傳遞的供應商的產品。
要提供此功能 , 需要為 SendToProducts Button 的 Click 事件創建一個 Event Handler 。在步驟 3 中 , 我們添加了 SuppliersSelectedIndex 屬性 , 該屬性返回選定單選按鈕行的索引。相應的SupplierID 可從 GridView 的 DataKeys 集合進行檢索 , 并且可使用Response.Redirect("url") 將用戶轉到 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID?。
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 按鈕 , 則SuppliersSelectedIndex 的值將為 -1 , 這將引發拋出一個異常 , 因為 -1 超出了 DataKeys 集合索引的范圍。這并不是我們關心的問題 , 但是 , 如果您決定像步驟 3 中討論的那樣更新 RowCreated Event Handler , 初始就會在GridView 中選定第一個單選按鈕。
要使解決SuppliersSelectedIndex 的值為 -1 的問題, 請在 GridView 的上方向頁面上添加一個 Web 標簽 控件。將其 ID 屬性設置為 ChooseSupplierMsg 、CssClass 屬性設置為 Warning 、EnableViewState 和Visible 屬性設置為 False 、Text 屬性設置為 “Please choose a supplier from the grid” 。CSS 類在 Styles.css 中定義 , 并以紅色、斜體、粗體和大字體文本顯示警告信息。通過將其 EnableViewState 和 Visible 屬性設置為 False ,除非控件的 Visible 屬性通過編碼設置為 True ,否則將不會呈現 Label 。
圖13 :?在 GridView 上方添加一個 Web 標簽 控件
接下來 , 擴充 Click Event Handler , 使之在SuppliersSelectedIndex 小于零的情況下顯示ChooseSupplierMsg Label , 否則將用戶重定位到~/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);?
????}?
}
在瀏覽器中訪問該頁面,并在從GridView 選擇供應商之前單擊 SendToProducts 按鈕。如圖 14 所示 , 這將顯示 ChooseSupplierMsg label 。接下來,選擇一個供應商,并單擊 SendToProducts 按鈕。這將快速鏈接到列出選定供應商提供的產品的頁面。圖 15 顯示了選定 Bigfoot Breweries 供應商時的 ProductsForSupplierDetails.aspx 頁面。
圖14 :?在未選定供應商的情況下顯示 ChooseSupplierMsg Label
圖15?:ProductsForSupplierDetails.aspx 頁面上顯示了選定供應商的產品
步驟5 :在同一頁面上顯示選定供應商的產品
在步驟4 中 , 我們了解了如何將用戶轉到其它 web 頁 , 從而顯示選定供應商的產品。或者,也可以在同一頁面上顯示選定供應商的產品可。為了說明這一點,我們將向 RadioButtonField.aspx 頁面添加另外一個 GridView ,從而顯示選定供應商的產品。
由于我們希望GridView 上的產品在選定供應商時顯示 , 因此 , 需要在 Suppliers GridView 的下方添加一個 Panel Web 控件 , 將其ID 設置為 ProductsBySupplierPanel 、Visible 屬性設置為 False 。在 Panel 內 , 添加文本 “Products for the Selected Supplier” , 其后面為名為ProductsBySupplier 的 GridView 。從 GridView 的智能標記 , 選擇將其綁定到一個名為ProductsBySupplierDataSource 的新ObjectDataSource 。
圖16 :?將 ProductsBySupplier GridView 綁定到一個新的 ObjectDataSource
接下來 , 將ObjectDataSource 配置為使用 ProductsBLL 類。由于我們僅希望檢索選定供應商提供的產品 , 請指定ObjectDataSource 應調用GetProductsBySupplierID(supplierID) 方法來檢索數據。在 UPDATE 、 INSERT 和 DELETE 選項卡中將下拉列表中選擇為 “(None)” 。
?
圖17 :?將 ObjectDataSource 配置為使用GetProductsBySupplierID(supplierID) 方法
圖18 :?在 UPDATE 、INSERT 和 DELETE 選項卡中將下拉列表設置為 “(None)”
在配置完SELECT 、UPDATE 、INSERT 和 DELETE 選項卡之后 , 單擊 Next 。由于 GetProductsBySupplierID(supplierID) 方法需要輸入參數 ,Create Data Source 向導將提示我們指定參數值的來源。
此處 , 我們有幾個選項來指定參數值的來源。我們可以使用默認的Parameter 對象 , 并且在 ObjectDataSource 的 Selecting Event Handler 中通過編碼將 SuppliersSelectedIndex 屬性值分配給Parameter 的 DefaultValue 屬性。請參閱?通過編碼設定 ObjectDataSource 參數值?教程, 復習通過編碼向 ObjectDataSource 參數分配參數值的內容。
或者 , 我們可以使用ControlParameter , 請參閱Suppliers GridView 的?SelectedValue 屬性?( 見圖 19 ) 。GridView 的 SelectedValue 屬性返回對應于?SelectedIndex 屬性?的 DataKey 值。為了保證此選項能夠正常工作 , 我們需要在單擊 ListProducts 按鈕時將 GridView 的 SelectedIndex 屬性通過編碼設置為選定行。作為附帶的好處 , 通過設置 SelectedIndex , 選定記錄將呈現為 DataWebControls Theme 中 定義的 SelectedRowStyle ( 黃色背景 ) 。
圖19 :?使用 ControlParameter 指定 GridView 的 SelectedValue 作為參數源
完成向導之后 ,Visual Studio 將自動為產品的數據字段添加字段。刪除ProductName 、CategoryName 和 UnitPrice BoundField 之外的所有 BoundField , 將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>
要完成此練習 , 我們需要在單擊ListProducts 時 , 將 GridView 的 SelectedIndex 屬性設置為SelectedSuppliersIndex , 將ProductsBySupplierPanel Pane 的Visible 屬性設置為 True 。要達到這個目的 , 請為 ListProducts Web 按鈕 控件的Click 事件創建一個 Event Handler , 并添加下列代碼 :
<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"?/>
如果未從GridView 選定供應商 , 頁面上將顯示 ChooseSupplierMsg Label , 而ProductsBySupplierPanel Panel 將隱藏。否則 , 如果已經選定供應商 , 則頁面上將顯示 ProductsBySupplierPanel , 并且更新 GridView 的SelectedIndex 屬性。
圖20 顯示了選定 Bigfoot Breweries 供應商 , 并且單擊“Show Products on Page” 按鈕之后的結果。
圖20 :?在同一頁面上列出了 Bigfoot Breweries 提供的產品
小結
正如在?使用具有 Details DetailView 功能的可選主GridView 的主/明細報表?教程中討論的一樣 , 可使用其ShowSelectButton 屬性設置為 true 的 CommandField 從 GridView 選擇記錄。但是, CommandField 的按鈕既可作為正常的按鈕和鏈接顯示,也可作為圖像顯示。另一個選行用戶界面是在每個 GridView 行中提供一個單選按鈕或一個復選框。在本教程中,我們探討了如何添加一列單選按鈕。
遺憾的是 , 添加一列單選按鈕并非人們期望的那樣直接或簡單。單擊按鈕時并沒有任何可添加的內置RadioButtonField , 并且在TemplateField 中使用RadioButton Web 控件會引入一系列問題。最后 , 要想提供這樣的界面 , 我們必須創建一個定制 DataControlField 類 , 或者在 RowCreated 事件期間向TemplateField 插入適當的 HTML 代碼。
我們已經探討了如何添加一列單選按鈕,下面我們將把注意力集中到添加一列復選框上面。通過一列復選框,用戶可以選擇一個或者多個 GridView 行,然后對所有選定行完成某些操作(例如,從基于 web 的郵件客戶端選擇一系列郵件,然后選擇刪除所有選定的郵件)。在下個教程中,我們將探討如何添加復選框列。
快樂編程!
?
轉載于:https://www.cnblogs.com/uddgm/articles/5451541.html
總結
以上是生活随笔為你收集整理的为 GridView 添加一列单选按钮50的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安徽省允许卖自己酿的散酒吗?
- 下一篇: Ruby Cucumber环境