解决datalist中radiobutton单选的问题

ASP.NET中,本来RadioButton的Groupname是为了标识同一组RadioButton准备的,也就是说如果Groupname相同,那么认为是同一组单选按钮,同一时间只能选中其中一个。翻译成客户端代码的时候,会把Groupname翻译成html里面的name。

但是DataGrid或DataList模板列中,如果放置了一个RadioButton控件,其设置的Groupname是无效的。原因在于,在转换成客户端代码时,控件的name会变成DataList名:_ct行号:Groupname名。这样,每一行的RadioButton也就有了不同的name,这样html就会认为是不同组的RadioButton,也就造成了控制单选无效的结果。

解决方法有几种,一种是RadioButton的AutoPost设为true,这样每次点击单选按钮就会回传,然后在触发的代码里把其他按钮的选择清空。但是这样频繁回传,不是一个好办法。有篇文章也写到了一种javascript控制的方法,原理是差不多,实现办法看似比较笨,但很管用。也就是在每一行的RadioButton的onclick事件里,将其他行的RadioButton选择一行行清空。打个比方,假如只有一个顾客吃饭,他从其他桌改坐二号桌,那么就去检查清理下其他桌上有没遗漏什么东西,清理一号桌,清理三号桌,清理四号桌……

假如DataList名叫DataListABC,模板列里面的RadioButton叫RadioButtonABC.
     for(int i=0;i<DataListABC.Items.Count;i++)
     {
      RadioButton rb=(RadioButton)DataListABC.Items[i].FindControl("RadioButtonABC");
      sTemp="";
      for(int j=0;j<DataListABC.Items.Count;j++)
      {
       if(j!=i)
       {
        RadioButton rb2=(RadioButton)DataListABC.Items[j].FindControl("RadioButtonABC");
        sTemp=sTemp+"uncheck('"+rb2.ClientID+"');";
       }
      }
      if(sTemp!="")
      {
       rb.Attributes.Add("onclick",sTemp);
      }
     }
然后在页面的html的head部分加上一段javascript。
function uncheck(a)
{ var targetElement;
targetElement=document.getElementById(a);
if(targetElement!=null)
{ targetElement.checked=false;
}
}

二、javascript脚本解决方法

javascript代码:
<script language="javascript" type="text/javascript">
function clickit() {
        var dom=document.all;
        var el=event.srcElement;
        if(el.tagName=="INPUT"&&el.type.toLowerCase()=="radio")
        {
                for(i=0;i<dom.length;i++)
                {
                        if(dom[i].tagName=="INPUT"&&dom[i].type.toLowerCase()=="radio")
                        {
                                dom[i].checked=false;
                        }
                }
        }
        el.checked=true;
}
</script>

单选按钮的代码如:
<asp:RadioButton ID="RadioButton1" runat="server" onclick="clickit();"
                 Text='<%# DataBinder.Eval(Container.DataItem, "CARD_NBR")%>' />

 

 

其他见解:

实看似“正统”的思路未必是精准的,编程最好务求精准而不仅仅是正统。FindControl几乎不去使用才更能够又快有准地找到控件——控件它自己来触发事件而不是我们去找它。在GridView的模板中,我们可能放入任何东西,说不定哪一天你把CheckBox放入一个复杂的控件中(例如MultiView之类的)。FindControl让人觉得又慢又不适合很好地对设计进行维护。应该让CheckBox“主动通知我们”而不是我们去寻找它,这就是 MVP 编程的意义。只是要加上一点:CheckBox可以自身同时带着它的标识信息。

这样,界面设计可以是这样的:

HTML code
<asp:TemplateField HeaderText="abc" SortExpression="ytf"> <ItemTemplate> <asp:CheckBox ID="chk" runat="server" 哈哈='<%# Eval("key_field") %>' OnCheckedChanged="chk_CheckedChanged" /> </ItemTemplate> </asp:TemplateField>



设计时可以为服务器控件随意增加任何新的属性,它会写入控件的Attributes集合中,并且当你变成修改它时控件会自动在回发之间维护这个状态值。我这里就随便起了一个名字为“哈哈”的属性,当GridView被绑定时它的值使用Eval绑定为数据库中的一个标识值(通常是记录主键值)。

C# code
System.Collections.Generic.List<string> chks = new System.Collections.Generic.List<string>(); protected void chk_CheckedChanged(object sender, EventArgs e) { CheckBox chk = (CheckBox)sender; chks.Add(chk.Attributes["哈哈"]); }



每一个CheckBox在事件中都将自己的“哈哈”这个属性的值保存入chks。如果在界面上更改10个CheckBox,那么chk_CheckedChanged方法就会执行10次。然后就可以在你的Button的click事件处理程序中直接遍历chks集合。

所有的关于属性更改的事件都是在回发事件之前触发的,因此会先调用所有的 chk_CheckedChanged 方法,之后才调用 Button1_Click 方法。

posted on 2011-05-17 17:29  carekee  阅读(1123)  评论(0编辑  收藏  举报