[转]在ASP.NET的datagrid中使用radio button的历程

时间:2021-11-15 15:32:42

赤字先生 发表于 2006-10-16 17:43:39

在一个项目中,要在一个datagrid中使用RadioButton,就是一列中显示一组RadioButton,在这一列中是互斥的,每次只能选择一个RadioButton。 如下图:

[转]在ASP.NET的datagrid中使用radio button的历程

       一开始,尝试使用服务器控件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。

         这种文章的作者是及其不负责任的,浪费了很多人的时间。