如何对 RadioButtons 进行分组






4.88/5 (124投票s)
本文介绍了如何在 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 使用 GroupName
和 UniqueID
的串联作为“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;
}