动态加载用户控件ASP.net中的无线电选项GroupName问题

时间:2011-02-28 20:45:06

标签: .net asp.net user-controls radio-button

我有用户控制

<table style="border-width: 0">
    <tr>
        <td style="vertical-align: middle;">
            <asp:RadioButton ID="rdOption" runat="server" Text="I m testing"  
                GroupName="Questions" oncheckedchanged="rdOption_CheckedChanged" 
                AutoPostBack="True"/>
        </td>
        <td style="vertical-align: middle; padding-left: 10px">
            <asp:TextBox ID="txtOthers" runat="server" CssClass="txtbox" Visible="false"></asp:TextBox>
        </td>
    </tr>
</table>

protected void Page_Load(object sender, EventArgs e)
    {
        rdOption.GroupName = "myGroup";
        rdOption.Text = Option.OptionDesc;
    }
在Survery.aspx上

我动态加载了该用户控件

 foreach (clsOptions option in _CurrentQuestion.Options)
        {
            UserControls_OptionField ctrl = Page.LoadControl("~/UserControls/OptionField.ascx") as UserControls_OptionField;
            ctrl.Option = option;
            pnlOption.Controls.Add(ctrl);
        }

问题是每个选项都有不同的组名,如下所示。这就是为什么选项不能正常工作并且可以选择所有选项,而在MCQ中只能选择一个选项。

<input id="ContentPlaceHolder1_ctl01_rdOption" type="radio" name="ctl00$ContentPlaceHolder1$ctl01$myGroup" value="rdOption">

<input id="ContentPlaceHolder1_ctl02_rdOption" type="radio" name="ctl00$ContentPlaceHolder1$ctl02$myGroup" value="rdOption">

enter image description here

5 个答案:

答案 0 :(得分:4)

正如所有人建议的那样,这是设计使然,以后会被视为一个bug。

Joel建议的控件非常棒,除了它会覆盖整个Render逻辑,因此,不会使用写入此控件后框架中的任何增强。

所以,我建议用以下代码替换其他控件中的Render()方法:

    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
        using (var stringWriter = new StringWriter())
        using (var htmlWriter = new HtmlTextWriter(stringWriter))
        {
            base.Render(htmlWriter);
            var tagText = stringWriter.ToString();

            tagText = Regex.Replace(tagText, "name=\"(\\S+)\"", "name=\"" + GroupName + "\"");

            writer.Write(tagText);
        }
    }

好处是能够保留可能来自基础渲染的所有额外内容。

请注意,您可以:

  • 在类中添加另一个属性,根据属性是否设置,使这个不同的渲染行为可选

  • 通过web.config使所有<asp:RadioButton:声明引用您的自定义控件而不更改它们:

  <system.web>
    <pages>
      <tagMapping>
        <add tagType="System.Web.UI.WebControls.RadioButton" mappedTagType="WebformsLibrary.CustomRadioButton" />
      </tagMapping>
    </pages>
  </system.web>

WebformsLibrary.CustomRadioButton是哪个类。

答案 1 :(得分:3)

我认为这是自1.0以来在ASP.Net中的bug很棒,他们完全忘记了^^ )。

您可以尝试使用适用于Repeater(或任何数据绑定控件)的解决方案,但也应该适用于动态UserControl。

问题是ASP.Net为不同的NamingContainers呈现不同的唯一名称,因此RadioButtons会获得不同的GroupNames。

http://weblogs.asp.net/joseguay/archive/2008/07/24/having-radiobuttons-on-a-repeater-or-datalist.aspx

将它放在页面的HEAD部分:

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;
}

使用适当的参数将clientide onclick事件添加到RadioButtons:

string script = "SetUniqueRadioButton('rdOption.*myGroup',this)";
rdOption.Attributes.Add("onclick", script);

[未经测试]

答案 2 :(得分:0)

您需要将每个RadioButtons上的“GroupName”属性设置为相同的内容。

编辑:如果你使用.net 4,那么我认为使用ClientIDMode属性来控制ID的工作。否则,你正在做的是asp.net中的已知问题(通常表现为将单选按钮放在转发器/列表视图中)。

您将需要自己控制并实现INamingContainer接口以适用于您的无线电或使用不带用户控件的RadioButtonGroup。我还看到了一些使用javascript来强制执行仅一种选择模式的解决方案。

答案 3 :(得分:0)

和蒂姆说,这是一个已知的错误。这是一个继承自RadioButton的usercontrol,但解决了您遇到的问题:http://www.codeproject.com/KB/webforms/How_group_RButtons.aspx

答案 4 :(得分:0)

我发现这个解决方案更好。它类似于Tim Schmelter的solution,但我认为将名称设置为它的意图更容易,这样它就是什么您希望在使用它或查看它时,并且您不必手动设置每次单击一个单选按钮是否都被选中。

function fixRadioButtons(s, e) {
    var re = /^(?:.*\$)?(.*)$/;
    for (i = 0; i < document.forms[0].elements.length; i++) {
        var elm = document.forms[0].elements[i];
        if (elm.type == 'radio') {
            var match = re.exec(elm.name);
            elm.name = match[1];
        }
    }
}

然后通过JS - reference

在回发上调用该函数
// This code runs a function on postback
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(fixRadioButtons);

AND / OR:在后面的代码(VB.NET) - reference

ClientScript.RegisterStartupScript(Me.GetType(), "Javascript", "fixRadioButtons(null, null);", True)

请注意,如果您希望每次都能运行它,而不仅仅是在回发时运行,那么您可能无论如何都需要使用ClientScript.RegisterStartupScript