我有一个模板控件(转发器)列出了一些文本和其他标记。每个项目都有一个与之关联的单选按钮,使用户可以选择转发器创建的其中一个项目。
转发器将radiobutton设置为使用默认ASP.NET命名约定生成的id和名称,使每个radiobutton成为一个完整的“组”。这意味着所有的无线电按钮彼此独立,遗憾的是,这意味着我可以同时选择所有的无线电按钮。 radiobutton具有用于设置公共名称的聪明属性“groupname”,因此它们被组合在一起,因此应该是相关的(因此我一次只能选择一个)。问题是 - 这不起作用 - 转发器确保id和名称(控制分组)不同。
由于我使用转发器(可能是listview或任何其他模板化的数据绑定控件),我无法使用RadioButtonList。那么这让我离开了什么?
我知道我之前遇到过这个问题并解决了它。我知道几乎每个ASP.NET程序员都必须拥有它,所以为什么我不能google并找到解决问题的可靠方法呢?我遇到了通过JavaScript强制执行分组的解决方案(丑陋!)甚至将无线电按钮作为非服务器控件处理,迫使我执行Request.Form[name]
来读取状态。我还尝试在PreRender
事件上尝试覆盖name属性 - 不幸的是,拥有的页面和母版页会再次覆盖此名称以反映完整的id / name,因此我最终得到了相同的错误结果。
如果你没有比我发布的更好的解决方案,你仍然非常欢迎你发表你的想法 - 至少我会知道我的朋友'杰克'是关于ASP.NET有时会搞砸的事情;)< / p>
答案 0 :(得分:8)
ASP.NET提示:在Repeater中使用RadioButton控件
这是JavaScript函数的代码:
function SetUniqueRadioButton(nameregex, current)
{
re = new RegExp(nameregex);
for(i = 0; i < document.forms[0].elements.length; i++)
{
elm = document.forms[0].elements[i]
if (elm.type == 'radio')
{
if (re.test(elm.name))
{
elm.checked = false;
}
}
}
current.checked = true;
}
代码通过ItemDataBound事件链接到Repeater。要使其正常工作,您需要知道Repeater控件的名称,以及您分配给RadioButtons的GroupName。在这种情况下,我使用rptPortfolios作为Repeater的名称,并使用Portfolios作为组名:
protected void rptPortfolios_ItemDataBound(object sender,
RepeaterItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType
!= ListItemType.AlternatingItem)
return;
RadioButton rdo = (RadioButton)e.Item.FindControl("rdoSelected");
string script =
"SetUniqueRadioButton('rptPortfolios.*Portfolios',this)";
rdo.Attributes.Add("onclick", script);
}
参考:http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c12371/
答案 1 :(得分:7)
Google-fu:asp.net radiobutton repeater problem
确实是身份损失的不幸后果。我的想法是创建一个 - 或者选择一个可用的 - 自定义控件,在客户端上添加对同名的支持。
答案 2 :(得分:6)
Vladimir Smirnov已经创建了一个很棒的自定义控件来解决这个问题。我们在我们的项目中一直使用GroupRadioButton,它一直与转发器内部创建的单选按钮完美配合,转发器外部的其他按钮都是同一组的一部分。
答案 3 :(得分:6)
我使用jQuery脚本:
<script type="text/javascript">
function norm_radio_name() {
$("[type=radio]").each(function (i) {
var name = $(this).attr("name");
var splitted = name.split("$");
$(this).attr("name", splitted[splitted.length - 1]);
});
};
$(document).ready(function () {
norm_radio_name();
});
// for UpdatePannel
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
norm_radio_name();
});
</script>
答案 4 :(得分:5)
我知道这是一篇旧帖子,但这是我最后用listview做的事情。我的listview受到VB代码隐藏的约束,所以我不确定这是否适用于转发器,但我想它可能类似。
我所做的是处理radiobuttons的OnCheckChanged事件,其功能是取消选择任何其他单选按钮。然后,当我离开页面时,我查找了所选的单选按钮。
此解决方案避免使用JavaScript和jQuery,并完全忽略GroupName问题。它并不理想,但它的作用是(I)预期的。我希望这对其他人有帮助。
标记:
<asp:ListView ID="lvw" runat="server">
<LayoutTemplate>`
<table>
<th>Radio</th>
<tr id="itemPlaceholder"></tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:RadioButton ID="rdbSelect" runat="server" AutoPostBack="true"
OnCheckedChanged="rdbSelect_Changed"/></td>
</tr>
</ItemTemplate>
</asp:ListView>
代码:
Protected Sub rdbSelect_Changed(ByVal sender As Object, ByVal e As System.EventArgs)
Dim rb1 As RadioButton = CType(sender, RadioButton)
For Each row As ListViewItem In lvw.Items
Dim rb As RadioButton = row.FindControl("rdbSelect")
If rb IsNot Nothing AndAlso rb.Checked Then
rb.Checked = False
End If
Next
rb1.Checked = True
End Sub
然后点击提交按钮时:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
For Each row As ListViewItem In lvw.Items
Dim rb As RadioButton = row.FindControl("rdbSelect")
Dim lbl As Label
If rb IsNot Nothing AndAlso rb.Checked = True Then
lbl = row.FindControl("StudentID")
Session("StudentID") = lbl.Text
End If
Next
Response.Redirect("~/TransferStudent.aspx")
End Sub
答案 5 :(得分:3)
这可能会好一点......
我有一个usercontrol,它实际上是一个转发器内的一组radiobuttons,usercontrol的每个实例都有一个名为FilterTitle的公共属性,每个实例都是唯一的。
将这两个属性添加到您的radiobutton,用您自己的公共属性名称
替换FilterTitleonclick='<%# "$(\"input[name$=btngroup_" + FilterTitle + "]\").removeAttr(\"checked\"); $(this).attr(\"checked\",\"checked\");" %>' GroupName='<%# "btngroup_" + FilterTitle %>'
更简单..
onclick="$('input[name$=btngroup1]').removeAttr('checked'); $(this).attr('checked','checked');" GroupName="btngroup1"
答案 6 :(得分:2)
为了完整起见,这是一个纯粹的Javascript解决方案。
只需将此onclick
属性添加到您的RadioButton
元素中(将 GroupName 替换为您的RadioButton
的GroupName):
<asp:RadioButton ... GroupName="GroupName" onclick="SelectRadioButton('GroupName$',this)" ... />
并在您的网页中加入此Javascript:
<script type="text/javascript">
function SelectRadioButton(regexPattern, selectedRadioButton)
{
regex = new RegExp(regexPattern);
for (i = 0; i < document.forms[0].elements.length; i++)
{
element = document.forms[0].elements[i];
if (element.type == 'radio' && regex.test(element.name))
{
element.checked = false;
}
}
selectedRadioButton.checked = true;
}
</script>
答案 7 :(得分:2)
创建自定义控件并将UniqueID覆盖到listview UniqueID + GroupName
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MYCONTROLS
{
[ToolboxData("<{0}:MYRADIOBUTTON runat=server></{0}:MYRADIOBUTTON >")]
public class MYRADIOBUTTON : RadioButton
{
public override string UniqueID
{
get
{
string uid = base.UniqueID;
//Fix groupname in lisview
if (this.Parent is ListViewDataItem && GroupName != "")
{
uid = this.Parent.UniqueID;
uid = uid.Remove(uid.LastIndexOf('$'));
uid += "$" + GroupName;
}
return uid;
}
}
}
}
这是一个继承自RadioButton的自定义控件(公共类MYRADIOBUTTON:RadioButton)。 如果你在课堂上什么都不做,你会得到一个普通的RadioButton。重写UniqueId,您可以更改name属性的呈现方式。 要使名称对页面上的其他控件(列表视图外)保持唯一,您可以从ListView获取UniqueId并将GroupName添加到该名称并将其添加到RadioButton。
这解决了在listview中的不同行上分组RadioButtons的问题。您可能希望添加一些带有属性的逻辑来打开/关闭此功能,使其行为类似于普通的RadioButton。
答案 8 :(得分:2)
我知道这个问题有点老了,但我认为这可能会对某些人有所帮助,因此我可以解决这个问题。
这个问题有两个部分:
我在Repeater的Radio按钮上遇到了类似的问题。我找到了部分解决方案: Simple fix for Radio Button controls in an ASP.NET Repeater using jQuery
请阅读上述文章以了解该问题。我引用了这篇文章,这是很好的帮助。如上所述,这个问题有两个部分,第一部分是防止一次选择多个单选按钮。其次,要知道在服务器端代码中单击了哪个单选按钮。上面文章中公布的解决方案仅适用于第一部分。但是,那里写的代码以及在那里发布的解决方案的更新对我来说不起作用。所以我不得不修改它以使其正常工作。这是我的解决方案。
我想用投票按钮创建投票。我的单选按钮(ID)的名称是PollGroupValue,其中Groupname在转发器中设置为PollGroup。记住ASP.net中的Groupname属性在生成的html中呈现为name属性。我的代码如下:
<script type="text/javascript">
/* Step-01: */
$(document).ready(function () {
/* Step-02: */
$("[name*='PollGroup']").each(function () {
$(this).attr('ci-name', $(this).attr('name'));
});
/* Step-03: */
$("[name*='PollGroup']").attr("name", $("[name*='PollGroup']").attr("name"));
$('#Poll1_BtnVote').click(function (e) {
/* Step - 04: */
if ($("[name*='PollGroup']").filter(':checked').length == 0) {
alert('Please select an option.');
e.preventDefault();
}
/* Step - 05: */
$("[name*='PollGroup']").each(function () {
$(this).attr('name', $(this).attr('ci-name'));
});
});
});
第1步: 每当在转发器中使用单选按钮时,其组名都会被更改,因为asp.net会对其进行更改以使其唯一。因此,每个单选按钮都会获得不同的组名(客户端生成的标记中的名称属性)。因此,用户可以同时选择所有选项。通过使用jquery代码解决此问题,如后续注释所述。
第2步: 此代码块创建一个名为ci-name的新custome属性,并将name属性的原始值复制到此新自定义属性中。轮询中的每个单选按钮都会重复此过程。这一步将在后面的步骤中帮助我们。
第3步: 此代码块将poll中所有单选按钮的name属性值设置为第一个单选按钮的name属性值。此步骤可防止用户一次选择多个选项。
第4步: 此代码在投票按钮单击事件的事件处理程序内,检查用户是否已检查至少一个选项。如果他没有,则会显示错误消息。
第5步: 此代码在投票按钮单击事件的事件处理程序内,将所有单选按钮的name属性值设置为其原始值。这是通过从自定义属性ci-name复制值来实现的。这允许asp.net服务器端代码知道实际点击了哪个按钮。
答案 9 :(得分:1)
我也对这个错误感到困惑,并决定放弃转发器,转而使用内部控件动态构建一个表。在您的用户控件或页面上,只需添加以下元素:
<asp:Table ID="theTable" runat="server">
<asp:TableHeaderRow runat="server">
<asp:TableHeaderCell runat="server" Text="Column 1"/>
<asp:TableHeaderCell runat="server" Text="Column 2"/>
<asp:TableHeaderCell runat="server" Text="Column 3"/>
</asp:TableHeaderRow>
</asp:Table>
然后使用单选按钮和其他所需控件在后面的代码中添加数据行。你当然可以和其他元素一样做,比如DIV:
<div runat="server" ID=theDiv">
</div>
但是让我们仍然希望ASP.NET团队能够解决转发器和列表视图这个不幸的问题。我仍然喜欢转发器控制并尽可能使用它。
答案 10 :(得分:1)
这是一种使用反射的纯服务器端方法。 RadioButton
控件使用UniqueGroupName
属性来确定组名。组名称缓存在_uniqueGroupName
字段中。通过使用反射设置此字段,我们可以覆盖默认组名称,并使用在转发器中所有单选按钮上相同的组名称。请注意,此代码必须在“RadioButton”控件的“PreRender”事件中运行,以确保新的组名称在帖子后面保留。
protected void rbOption_PreRender(object sender, EventArgs e)
{
// Get the radio button.
RadioButton rbOption = (RadioButton) sender;
// Set the group name.
var groupNameField = typeof(RadioButton).GetField("_uniqueGroupName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
groupNameField.SetValue(rbOption, "MyGroupName");
// Set the radio button to checked if it was selected at the last post back.
var groupValue = Request.Form["MyGroupName"];
if(rbOption.Attributes["value"] == groupValue)
{
rbOption.Checked = true;
}
}
答案 11 :(得分:0)
对于每个人来说,这可能不是理想的解决方案,但我使用jQuery进行了以下操作。
<asp:RadioButton ID="rbtnButton1" groupName="Group1" runat="server" />
<asp:RadioButton ID="rbtnButton2" groupName="Group1" runat="server" />
etc...
然后在母版页中包含以下代码。 (或所有页面)
$(function() {
//This is a workaround for Microsoft's GroupName bug.
//Set the radio button's groupName attribute to make it work.
$('span[groupName] > input').click(function() {
var element = this;
var span = $(element).parent();
if (element.checked) {
var groupName = $(span).attr('groupName');
var inputs = $('span[groupName=' + groupName + '] > input')
inputs.each(function() {
if (element != this)
this.checked = false;
});
}
});
});
答案 12 :(得分:0)
通过忽略HtmlInputControl.RenderAttributes()
属性来自定义控件/覆盖以解决RenderedNameAttribute
方法:
/// <summary>
/// HACK: For Microsoft's bug whereby they mash-up value of the "name" attribute.
/// </summary>
public class NameFixHtmlInputRadioButton : HtmlInputRadioButton
{
protected override void RenderAttributes(HtmlTextWriter writer)
{
// BUG: Usage of 'HtmlInputControl.RenderedNameAttribute'
// writer.WriteAttribute("name", this.RenderedNameAttribute);
writer.WriteAttribute(@"name", Attributes[@"Name"]);
Attributes.Remove(@"name");
var flag = false;
var type = Type;
if (! string.IsNullOrEmpty(type))
{
writer.WriteAttribute(@"type", type);
Attributes.Remove(@"type");
flag = true;
}
base.RenderAttributes(writer);
if (flag && DesignMode)
{
Attributes.Add(@"type", type);
}
writer.Write(@" /");
}
}
答案 13 :(得分:0)
我使用相同的Technic取消选中其他收音机和jquery,请找到下面的代码
<asp:RadioButton ID="rbSelectShiptoShop" runat="server" onchange="UnCheckRadio(this);" CssClass="radioShop" />
和下面的脚本
function UnCheckRadio(obj) {
$('.radioShop input[type="radio"]').attr('checked', false);
$(obj).children().attr('checked', true);
}