在一個項目中,要在一個datagrid中使用RadioButton,就是一列中顯示一組RadioButton,在這一列中是互斥的,每次只能選擇一個RadioButton。 如: 一開始,嘗試使用伺服器控制項RadioButton作為DataGrid模板列的控制項來實現: <asp:DataGrid id="countriesGrid" runat="server" DataKeyField="ID" AutoGenerateColumns="False"> <Columns> <asp:TemplateColumn> <ItemTemplate> <asp:RadioButton id="selectRadioButton" runat="server" GroupName="country" /> </ItemTemplate> </asp:TemplateColumn> </Columns> </asp:DataGrid> 在這裡嘗試使用GroupName="country"來對這一列的radio button進行分組,使得這一列所有的radio button成為一組。 但是開啟頁面發現,產生的radio button沒有成為一組,每個都可以選中。 查看用戶端產生的原始碼發現: <tr> <td><input id="countriesGrid__ctl2_selectRadioButton" type="radio" name="countriesGrid:_ctl2:country" value="selectRadioButton" /> </td> </tr> <tr> <td><input id="countriesGrid__ctl3_selectRadioButton" type="radio" name="countriesGrid:_ctl3:country" value="selectRadioButton" /> </td> </tr> 裡面radio button的name屬性就是group name屬性,用來分組的。 顯然產生的html代碼把group name改變了。因此這一列的radio button不能成為一組。 問題的關鍵就在這裡,自動產生的radio button 的group name不是相同的,因此不能成為一組。只要radio button的group name相同就解決問題了。 只要使得radio button的group name相同,有兩個解決方案。 現在分別來說: 一個是使用非伺服器端控制項(不帶runat="server"的控制項,帶runat="server"的html控制項也不行): <ItemTemplate> <input type=radio name="RadioName" value='<%# DataBinder.Eval(Container.DataItem, "IntegerValue")%>'/> </ItemTemplate> 使用這樣的控制項產生的html代碼是: <tr> <td><input id="countriesGrid__ctl2_selectRadioButton" type="radio" name="RadioName" value="1" /> </td> </tr> <tr> <td><input id="countriesGrid__ctl3_selectRadioButton" type="radio" name="RadioName" value="2" /> </td> </tr> 這樣產生的radio button的group name被改變,因此可以成為一組radio button了。 但是這樣又帶來了問題。 因為非伺服器端控制項是不保持狀態的,這意味著每次向伺服器提交以後,radio button的選擇將會丟失。每次提交以後前面選擇的radio button又變為非選擇狀態了。 在網上的文章對這個問題有解決的方法,就是使用一段java script,還要加一個隱藏欄位, 在每次頁面重新整理時自動選擇上原來選擇的radio button。 雖然比較麻煩,但是問題還是解決了。 可是還有一個問題,如何獲得哪個radio button選中了呢?因為這些radio button是非伺服器端的啊。 radio button是作為一個表單的,每次頁面提交的時候,可以在Request.Forms集合裡面找到以radioName(radio button的組名)為key的索引值。該索引值就是當前選中的radio button的value屬性值。 像上面的例子,如果第一個radio button被選中,則Request.Forms["RadioName"]就是“1”。 第二個被選中就是“2”。這樣是可以得到哪個radio button被選中。 可是這樣的方法不可以得到datagrid的哪一行的radio button被選中。 而這是我們使用datagrid時一般要得到的。 而且,如果我們要用程式的方法來選中其中一個radio button,又怎麼實現呢? 因為在ASP.NET裡,後端代碼是得不到非伺服器端控制項的狀態的。 說到這裡,我們發現,使用非伺服器端控制項會帶來很多問題。因為是非伺服器端控制項,後端代碼無法訪問這些控制項的狀態,我們無法通過datagrid1.Items[0].Controls[1] as RadioButton的形式得到radio button控制項的引用來對控制項進行操作。 只能使用指令碼的方法來進行一些處理,因此就不能實現我們想要的一些功能。 所以最後還是迴歸到使用伺服器端控制項上來。 伺服器端控制項的問題就是自動產生的radio button的group name 不相同,從而使得不能成為一組。 方法一: 既然不能自動實現選中一個radio button清除先前選中的radio button的狀態,那可以用程式的方法。就是響應radio button的狀態改變的事件,事件中清除其它選中的radio button的狀態。 這樣的話,每次選中一個radio button都會進行提交,顯然不能“讓使用者得到最好的體驗”。 方法二: 網上有人用radiobuttonlist來實現,在一個儲存格放一個這樣的控制項,然後合并該列的其他儲存格,還要手工添加radiobuttonlist的項。 這種方法感覺非常醜陋,沒有一點美感。 方法三: 重新寫一個派生自RadioButton的伺服器控制項。產生name屬性時,使用group name屬性,從而每個產生的radio button的name屬性相同。 此方法見codeProject上的文章,還附帶源碼,說得非常詳細: http://www.codeproject.com/aspnet/How_group_RButtons.asp 這是比較完美的解決方案了。 因為是伺服器控制項,我們可以通過datagrid1.Items[0].Controls[1] as RadioButton的方法來訪問到radio button控制項,進行完全的控制。 本文歸納了在ASP.NET的datagrid中使用radio button的研究思路,裡面的方法都是網上從各個角度解決這個問題的方法,也不是完全自己的思路, 有點“抄襲”之嫌哦。 不過總結一下對這個問題探索的過程,還是有裨益的。 在這個過程中,發現網上很多關於這個問題的文章,只是簡單把代碼貼上去,沒有一點注釋,沒有關於這個問題的解決思路,為什麼要這樣做,這樣做是解決什麼問題, 而全靠讀者去分析代碼的意義,為什麼要這樣寫。讀者是累垮了可能還沒看出到底是怎麼解決這個問題的。 而且有些代碼裡面居然還有bug。 這種文章的作者是及其不負責任的,浪費了很多人的時間。 |