2014年5月10日 星期六

多組RadioButtonList互斥

一個同事的發問...

他在畫面上放了 3 組 RadioButtonList,希望其中一組選到時,另兩組可以自動清空選擇,於是我寫了這個範例

基本上兩種做法,偷懶的做法是放個 UpdatePanel,把 RadioButtonList 們都扔進去,比較好的做法是用 javascript 在 client 上處理。

首先是偷懶的做法
這是 aspx,有 3 個 RadioButtonList,都設定 SelectedIndexChanged 事件和設定 AutoPostBack=true
<form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:RadioButtonList ID="rbl1" runat="server" RepeatDirection="Horizontal" RepeatLayout="Flow"
                OnSelectedIndexChanged="rbl1_SelectedIndexChanged" AutoPostBack="true">
                <asp:ListItem>Car</asp:ListItem>
                <asp:ListItem>Motocycle</asp:ListItem>
                <asp:ListItem>Bicycle</asp:ListItem>
            </asp:RadioButtonList>
            <br />
            <br />
            <asp:RadioButtonList ID="rbl2" runat="server" RepeatDirection="Horizontal" RepeatLayout="Flow"
                OnSelectedIndexChanged="rbl2_SelectedIndexChanged" AutoPostBack="true">
                <asp:ListItem>Apple</asp:ListItem>
                <asp:ListItem>Mango</asp:ListItem>
                <asp:ListItem>Pineapple</asp:ListItem>
            </asp:RadioButtonList>
            <br />
            <br />
            <asp:RadioButtonList ID="rbl3" runat="server" RepeatDirection="Horizontal" RepeatLayout="Flow"
                OnSelectedIndexChanged="rbl3_SelectedIndexChanged" AutoPostBack="true">
                <asp:ListItem>Frog</asp:ListItem>
                <asp:ListItem>Cat</asp:ListItem>
                <asp:ListItem>Dog</asp:ListItem>
            </asp:RadioButtonList>
        </ContentTemplate>
    </asp:UpdatePanel>
</form>
然後這是 aspx.cs
protected void rbl1_SelectedIndexChanged(object sender, EventArgs e)
{
    RadioButtonList radioButtonList = sender as RadioButtonList;
    if (radioButtonList.SelectedIndex > -1)
    {
        rbl2.SelectedIndex = -1;
        rbl3.SelectedIndex = -1;
    }
}

protected void rbl2_SelectedIndexChanged(object sender, EventArgs e)
{
    RadioButtonList radioButtonList = sender as RadioButtonList;
    if (radioButtonList.SelectedIndex > -1)
    {
        rbl1.SelectedIndex = -1;
        rbl3.SelectedIndex = -1;
    }
}

protected void rbl3_SelectedIndexChanged(object sender, EventArgs e)
{
    RadioButtonList radioButtonList = sender as RadioButtonList;
    if (radioButtonList.SelectedIndex > -1)
    {
        rbl2.SelectedIndex = -1;
        rbl1.SelectedIndex = -1;
    }
}

接著我們用 jquery 來做
一樣在 aspx 上放 3 個 RadioButtonList,然後把所有的 radio 都註冊 click 事件,當一個 radio 被 checked 時,往上找該 radio 的容器,然後把另兩個容器裡的 radio 都 uncheck
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="TestRadioButtonListExclusive.WebForm1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>用 jquery</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript">
        //註冊所有 radio 的 click 事件
        $(document).ready(function(){
            var containers=["<%=rbl1.ClientID %>","<%=rbl2.ClientID %>","<%=rbl3.ClientID %>"];

            for(var i=0;i<containers.length;i++){
                $("#"+containers[i]+" :radio").each(function(){
                    $(this).click(function(event){
                        SetOtherRadioButtonListUncheck(this);
                    });
                });
            }
        });
        
        function SetOtherRadioButtonListUncheck(rObj){
            var containers=["<%=rbl1.ClientID %>","<%=rbl2.ClientID %>","<%=rbl3.ClientID %>"];
            
            //抓上層容器, RepeatLayout=Flow的話抓最近的span, RepeatLayout=Flow的話抓最近的table
            //var parentObj=$(rObj).closest("span"); //RepeatLayout=Flow
            var parentObj=$(rObj).closest("table"); //RepeatLayout=Table
            var parentId=parentObj.get(0).id;
            
            for(var i=0;i<containers.length;i++){
                //若不是觸發事件的容器, 則將該容器裡的radio uncheck
                if(containers[i]!=parentId){
                    $("#"+containers[i]).find(":radio").each(function(){
                        this.checked=false;
                    });
                }
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:RadioButtonList ID="rbl1" runat="server" RepeatDirection="Horizontal" RepeatLayout="Table">
            <asp:ListItem>Car</asp:ListItem>
            <asp:ListItem>Motocycle</asp:ListItem>
            <asp:ListItem>Bicycle</asp:ListItem>
        </asp:RadioButtonList>
        <br />
        <br />
        <asp:RadioButtonList ID="rbl2" runat="server" RepeatDirection="Horizontal" RepeatLayout="Table">
            <asp:ListItem>Apple</asp:ListItem>
            <asp:ListItem>Mango</asp:ListItem>
            <asp:ListItem>Pineapple</asp:ListItem>
        </asp:RadioButtonList>
        <br />
        <br />
        <asp:RadioButtonList ID="rbl3" runat="server" RepeatDirection="Horizontal" RepeatLayout="Table">
            <asp:ListItem>Frog</asp:ListItem>
            <asp:ListItem>Cat</asp:ListItem>
            <asp:ListItem>Dog</asp:ListItem>
        </asp:RadioButtonList>
    </form>
</body>
</html>