在ASP.NET的Repeater中,groupname无法在多个单选按钮中起作用。

12

我有一个repeater,在repeater里面放了一个radiobutton控件,在代码背后我填充radiobutton控件的groupname,所以当我运行它时,我有一个包含许多行和一些带radiobutton的表:

  <asp:updatepanel id="UpdatePanel1" runat="server" updatemode="Conditional">
    <ContentTemplate>
        <asp:Repeater ID="Repeater1" runat="server" ViewStateMode="Enabled">
            <HeaderTemplate>
                <table class="table table-responsive table-bordered ">
                    <tr class="text-center" style="background-color: #6e6259; color: white;">
                        <th class="text-center">DESCRIPTION</th>
</HeaderTemplate>
            <ItemTemplate>
         <tr>
        <td style="padding-left: 20px;">
      <asp:RadioButton ID="rbtDinamic"  OnCheckedChanged="rbtDinamic_CheckedChanged" AutoPostBack="true"
           ViewStateMode="Enabled" Visible="false"  GroupName='<%#Eval("groupvalue") %>'   runat="server"/></td>
</ItemTemplate>
      <FooterTemplate>
    </table>
     </FooterTemplate>
    </asp:Repeater>
     </ContentTemplate>
      </asp:UpdatePanel>

在重复器的ItemDataBound事件中,我填充了groupname的值:

  Private Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
    Try
        If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then
            If CType(e.Item.FindControl("hdf1"), Label).Text = False Then
                CType(e.Item.FindControl("rbtDinamic"), RadioButton).Visible = True
                CType(e.Item.FindControl("rbtDinamic"), RadioButton).GroupName = CType(e.Item.FindControl("groupvalue"), Label).Text = False
            End If
        End If
    Catch ex As Exception          
    End Try
End Sub

但是当我运行它时,repeater会创建不同名称的组名:

Radiobutton row 1:
Repeater1$ctl05$1

Radiobutton row 2:

Repeater1$ctl06$1

因此,当选中同一组的其他单选按钮时,它会将所有单选按钮都选中,而不是取消选中。

我在论坛上找到了这段代码,但仅在我只有一个组名时才起作用,但我可以有多个组名:

  Protected Sub rbtDinamic_CheckedChanged(sender As Object, e As EventArgs)
    For Each item As RepeaterItem In Repeater1.Items
        Dim rbtn As RadioButton = DirectCast(item.FindControl("rbtDinamic"), RadioButton)
        rbtn.Checked = False
    Next
    DirectCast(sender, RadioButton).Checked = True
End Sub

但是可能会有多组单选按钮,所以在这种情况下我不能使用这段代码。

有没有其他方法可以做到这一点?谢谢。

3个回答

10
这是一个已知的bug,与在ItemTemplateAlternatingItemTemplate中使用RadioButton控件有关(更多信息)。这是由于Repeater在后台自动分配控件ID和组名时(假设使用动态ClientIDMode),可能会导致命名混乱。要解决此问题,请设置一个客户端函数,如下所示:
function setExclusiveRadioButton(name, current)
{
    regex = new RegExp(name);  

    for (i = 0; i < document.forms[0].elements.length; i++)
    {
        var elem = document.forms[0].elements[i];
        if (elem.type == 'radio')
        {
           elem.checked = false;
        }
    }
    current.checked = true;
}

稍后,将脚本定位于以下所示的单选按钮控件:
Private Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
    Try
        If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then
            If CType(e.Item.FindControl("hdf1"), Label).Text = False Then
                CType(e.Item.FindControl("rbtDinamic"), RadioButton).Visible = True
                CType(e.Item.FindControl("rbtDinamic"), RadioButton).GroupName = CType(e.Item.FindControl("groupvalue"), Label).Text = False
            End If
        End If

        ' put the proper client-side handler for RadioButton
        Dim radio As RadioButton = CType(e.Item.FindControl("rbtDinamic"), RadioButton)
        Dim script As String = "setExclusiveRadioButton('Repeater1.*[RadioButton_GroupName]', this)"

        radio.Attributes.Add("onclick", script)

    Catch ex As Exception          
    End Try
End Sub

注意:setExclusiveRadioButton方法的第一个参数应设置为此正则表达式约定:[repeater控件ID].*[RadioButton_GroupName]RadioButton_GroupName值可以使用Eval检索)。或者,您可以使用基本的HTML input type = radio 或使用 RadioButtonList 代替。
参考: 在Repeater中使用RadioButton控件 类似问题: 重复器内的radiobutton 在重复器中仅选择一个radiobutton ASP.NET - 重复器中的Radio Buttons

5

由于其他用户已经提供了问题的根本原因,所以我不会重复解释,但是我将为您提供基于Jquery的解决方案:

jQuery("[name$='$optValue']").attr("name",jQuery("[name$='$optValue']").attr("name"));

jQuery("[name$='$optValue]").click(function (){ 
                //set name for all to name of clicked 
                jQuery("[name$='$optValue]").attr("name", this.attr("name")); 
            });

使用 attr("name", jQuery("[name$='optValue']")) 将尝试选择页面上以 optValue 结尾的所有输入项,例如重复器中的 optValue 项。然后,它将更改所有 optValue 元素的第一个找到的值的 name 属性。在此处使用的 attr("name") 函数(以 'get' 格式使用)始终返回列表中的第一个。因此,所有选项按钮在 Html 中都具有相同的 'name' 属性,这样选择就可以正常工作。
此来源 学习一个很好的解决方法。

3
在客户端,将单选按钮的name设置为任何您喜欢的组名称,但在data-属性中记录生成的名称。
然后,在表单提交之前,将data-属性复制回name属性,以便ASP.NET能够在服务器上识别控件。
以下脚本可实现此功能:
<script type="text/javascript">
    $(document).ready(function (e) {            
        $("input[type='radio']").each(function (idx, elm) {
            var generatedName = $(elm).attr("name");
            $(elm).data("name", generatedName);
            $(elm).attr("name", "whatever-group-name");
        });

    });

    function onSubmit() {
        $("input[type='radio']").each(function (idx, elm) {
            var generatedName = $(elm).data("name");
            $(elm).attr("name", generatedName);
        });
    }
</script>

为了检测表单提交,您需要调用RegisterOnSubmitStatement。例如,在您的Page_Load方法中:
if (!IsPostBack)
{
    Page.ClientScript.RegisterOnSubmitStatement(Page.GetType(), "prepareSubmit", "onSubmit();");
}

谢谢您的回答,我有一个问题,idx和elm的值是多少? - Esraa_92
它们分别包含数组中元素的 索引 和 _元素本身_。jQuery会为您提供它们;无需初始化它们。只需在传递给 .each 方法的函数体内使用它们即可。 - Bozhidar Stoyneff
如果不是PostBack,if (!IsPostBack) 可能不应该存在,因为这个技巧在后续的 post-back 中停止工作。另外,这个特定的解决方案似乎也可以很好地与 AutoPostBack="true" 配合使用。 - esteewhy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接