65.9K
CodeProject 正在变化。 阅读更多。
Home

如何对 RadioButtons 进行分组

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (124投票s)

2004 年 8 月 12 日

CPOL

2分钟阅读

viewsIcon

881825

downloadIcon

12855

本文介绍了如何在 DataGrid、DataList、Repeater 等中使用 RadioButton 时对它们进行分组。

引言

“问题在哪里?你没听说过 GroupName 属性吗?” - 你可能会问我。当然,你是对的!但是...

让我们以一个普通的 DataGrid 为例,向其 Columns 集合中添加一个 TemplateColumn,并在该列中放置一个 RadioButton 控件(当您希望为用户提供从 DataGrid 项目中选择时,这可能很有用)。请参见下面的代码

<!-- Countries for selection -->
<asp:DataGrid id="countriesGrid" runat="server" 
         DataKeyField="ID" AutoGenerateColumns="False">
    <Columns>
        <asp:TemplateColumn>
            <ItemTemplate>
                <!-- 
                Draw attention at this control. 
                We would like to use radio-buttons to
                select single country from the list.
                -->
                <asp:RadioButton id="selectRadioButton" 
                    runat="server" GroupName="country" />
            </ItemTemplate>
        </asp:TemplateColumn>
        <asp:BoundColumn DataField="Country" HeaderText="Country" 
                                  HeaderStyle-Font-Bold="True" />
        <asp:BoundColumn DataField="Capital" HeaderText="Capital" 
                                  HeaderStyle-Font-Bold="True" />
    </Columns>
</asp:DataGrid>

现在,将一些数据绑定到 DataGrid 并运行您的 ASP.NET 应用程序。尝试单击“国家/地区”列表中的单选按钮。您可以选择一个国家/地区!...另一个...再一个...嗯!我们真的不想得到这种效果吗?

错误在哪里?我们已经为 RadioButton 指定了 GroupName,以便将它们视为来自同一个组,不是吗?看看从我们的 Web 窗体生成的 HTML 代码片段。你会看到类似这样的内容

<!-- Countries for selection -->
<table cellspacing="0" rules="all" border="1" id="countriesGrid" 
                              style="border-collapse:collapse;">
    <tr>
        <td> </td>
        <td style="font-weight:bold;">Country</td>
        <td style="font-weight:bold;">Capital</td>
    </tr>
    <tr>
        <td><input id="countriesGrid__ctl2_selectRadioButton" 
             type="radio" name="countriesGrid:_ctl2:country" 
             value="selectRadioButton" /></td>
        <td>USA</td>
        <td>Washington</td>
    </tr>
    <tr>
        <td><input id="countriesGrid__ctl3_selectRadioButton" 
             type="radio" name="countriesGrid:_ctl3:country" 
             value="selectRadioButton" /></td>
        <td>Canada</td>
        <td>Ottawa</td>
    </tr>
    <!-- etc. -->

单选按钮的“name”属性是不同的。为什么?答案就在这里。

呈现 RadioButton 控件时,ASP.NET 使用 GroupNameUniqueID 的串联作为“name”属性的值。因此,此属性取决于控件的 UniqueID,该属性又取决于所有者的 UniqueID 等。这是 ASP.NET 避免命名冲突的标准解决方案。由于“name”属性的值 <input type="radio" /> 用于标识提交表单时单选按钮组的回发数据,ASP.NET 开发人员决定将单选按钮组隔离在单个所有者控件的范围内(即,来自同一组的两个单选按钮不能有不同的直接所有者),否则可能会发生这种情况,您将使用两个都包含具有相同 GroupName 的单选按钮组的第三方控件 - 在这种情况下,所有单选按钮都将被视为来自单个组,这将带来不良行为。

现在你已经理解了错误的原因,但是如何实现我们想要的功能呢?在下一节中,我将为您提供解决方案。

问题的解决方案

为了解决我上面提出的问题,我创建了一个新的 GroupRadioButton Web 控件,该控件派生自 RadioButton

在此控件中,我更改了呈现方法,以便生成的 HTML 单选按钮的“name”属性现在仅取决于 GroupName

另一个修改是回发数据处理(已重写 IPostBackDataHandler 接口)。

GroupRadioButton 的其他功能与 RadioButton 相同。

有关详细信息,请参见 GroupRadioButton源代码

使用代码

现在,让我们修改初始表单。对“国家/地区”列表使用以下脚本

<%@ Register TagPrefix="vs" Namespace="Vladsm.Web.UI.WebControls" 
                                          Assembly="GroupRadioButton" %>
...
<!-- Countries for selection -->
<asp:DataGrid id="countriesGrid" runat="server" DataKeyField="ID" 
                                     AutoGenerateColumns="False">
    <Columns>
        <asp:TemplateColumn>
            <ItemTemplate>
                <vs:GroupRadioButton id="selectRadioButton" 
                runat="server" GroupName="country" />
            </ItemTemplate>
        </asp:TemplateColumn>
        <asp:BoundColumn DataField="Country" HeaderText="Country" 
                                  HeaderStyle-Font-Bold="True" />
        <asp:BoundColumn DataField="Capital" HeaderText="Capital" 
                                  HeaderStyle-Font-Bold="True" />
    </Columns>
</asp:DataGrid>

添加对 GroupRadioButton 程序集的引用,绑定 countriesGrid 的数据,并执行此表单。您将发现所有单选按钮都在同一个组中(即,用户只能选中其中一个)。

剩下的只是展示如何确定已选择了哪个国家/地区

using Vladsm.Web.UI.WebControls;
...
private void selectButton_Click(object sender, System.EventArgs e)
{
    // for each grid items...
    foreach(DataGridItem dgItem in countriesGrid.Items)
    {
        // get GroupRadioButton object...
        GroupRadioButton selectRadioButton = 
            dgItem.FindControl("selectRadioButton") as GroupRadioButton;

        // if it is checked (current item is selected)...
        if(selectRadioButton != null && selectRadioButton.Checked)
        {
            // sample data that was boud to the countriesGrid
            DataTable dataSource = DataSource.CreateSampleDataSource();

            // get country corresponding to the current item...
            DataRow row = 
              dataSource.Rows.Find(countriesGrid.DataKeys[dgItem.ItemIndex]);

            // ...and show selected country information
            selectedCountryInfo.Text = 
                String.Format("Selected country: {0}, Capital: {1}", 
                row["Country"], row["Capital"]);

            return;
        }
    }

    // there are no selected countries
    selectedCountryInfo.Text = String.Empty;
}
© . All rights reserved.