ASP.NET RadioButton возиться с именем (имя группы) - PullRequest
35 голосов
/ 18 декабря 2008

Я получил шаблонный элемент управления (повторитель), в котором перечислены некоторые тексты и другая разметка. С каждым элементом связан радиокнопка, позволяющая пользователю выбрать ОДИН из элементов, созданных ретранслятором.

Повторитель записывает радиокнопку, устанавливая ее идентификатор и имя, сгенерированные в соответствии с соглашением об именах ASP.NET по умолчанию, делая каждую радиокнопку полной группой. Это означает, что все радиокнопки независимы друг от друга, что, к сожалению, означает, что я могу выбрать все радиокнопки одновременно. Радиокнопка имеет умный атрибут «имя группы», используемый для установки общего имени, поэтому они группируются вместе и, следовательно, должны быть зависимыми (поэтому я могу выбрать только одно за раз). Проблема в том, что это не работает, ретранслятор удостоверяется, что идентификатор и, следовательно, имя (которое управляет группировкой) различаются.

Поскольку я использую ретранслятор (это мог быть просмотр списка или любой другой шаблонный элемент управления с привязкой к данным), я не могу использовать RadioButtonList. Так, где это оставляет меня?

Я знаю, у меня была эта проблема раньше, и я решил ее. Я знаю, что почти каждый программист ASP.NET должен был иметь его, так почему я не могу найти Google и найти надежное решение проблемы? Я столкнулся с решениями для принудительной группировки с помощью JavaScript (некрасиво!) Или даже для обработки радиокнопок как несерверных элементов управления, что заставило меня сделать Request.Form[name] для чтения статуса. Я также попытался поэкспериментировать с переопределением атрибута имени в событии PreRender - к сожалению, страница-владелец и главная страница снова переопределяют это имя, чтобы отразить полное имя / имя, поэтому я получаю тот же неправильный результат.

Если у вас нет лучшего решения, чем то, что я написал, вы все равно можете поделиться своими мыслями - по крайней мере, я буду знать, что мой друг «Джек» прав насчет того, как иногда портится ASP.NET;)

Ответы [ 14 ]

8 голосов
/ 01 января 2009

Совет ASP.NET: использование элементов управления 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, а также имя группы, которую вы назначаете для RadioButtons. В этом случае я использую rptPortfolios в качестве имени повторителя и 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);

}

REF: http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c12371/

7 голосов
/ 18 декабря 2008

Google-фу: проблема с ретранслятором радиоблокировки asp.net

Действительно, печальное последствие искажения идентификатора. Мой вариант - создать или выбрать один из множества доступных пользовательских элементов управления, который добавляет поддержку для того же имени на клиенте.

6 голосов
/ 29 августа 2010

Я использую скрипт 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>
6 голосов
/ 02 ноября 2009

Владимир Смирнов уже создал отличный пользовательский элемент управления, который решает эту проблему. Мы использовали GroupRadioButton в наших проектах, и он прекрасно работал с радиокнопками, созданными внутри ретранслятора, а другие вне ретранслятора были частью одной группы.

5 голосов
/ 04 мая 2011

Я знаю, что это старый пост, но вот что я закончил с просмотром списка. Мой просмотр списка связан с VB codebehind, поэтому я не уверен, будет ли это хорошо работать с ретранслятором, но я думаю, что он может быть похожим.

Что я сделал, так это обработал событие OnCheckChanged радиокнопок с помощью функции, которая отменяла выбор любых других радиокнопок. Затем я искал выбранную радиокнопку, когда ушел со страницы.

Это решение позволяет избежать JavaScript и jQuery и полностью игнорирует проблему GroupName. Это не идеал, но он функционирует так, как ожидалось. Я надеюсь, что это полезно для других.

Markup:

<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
3 голосов
/ 11 мая 2010

Это может быть немного лучше ..

У меня есть usercontrol, который по сути является набором радиокнопок внутри ретранслятора, каждый экземпляр usercontrol имеет открытое свойство FilterTitle, которое уникально для каждого экземпляра.

добавьте эти два свойства к вашей радиокнопке, заменив FilterTitle собственным именем общего свойства

onclick='<%# "$(\"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"
2 голосов
/ 01 января 2015

Я знаю, что этот вопрос немного устарел, но я думаю, что он может кому-нибудь помочь, поэтому публикую свое решение этой проблемы.

Эта проблема состоит из 2 частей:

  1. Для предотвращения выбора нескольких переключателей одновременно.
  2. Чтобы узнать, какая радио-кнопка была нажата в коде на стороне сервера.

У меня была похожая проблема с переключателем в Repeater. Я нашел частичное решение здесь: Простое исправление для элементов управления радиокнопками в ретрансляторе ASP.NET с использованием jQuery

Пожалуйста, прочитайте приведенную выше статью, чтобы получить представление о проблеме. Я сослался на эту статью, и это была хорошая помощь. Как уже упоминалось выше, эта проблема состоит из двух частей, во-первых, для предотвращения выбора более одной переключателя одновременно. Во-вторых, узнать, какая радио-кнопка была нажата в коде на стороне сервера. Решение, опубликованное в статье выше, сработало для меня только для первой части. Однако написанный там код, а также размещенные там обновления решения не сработали. Поэтому мне пришлось немного его изменить, чтобы он заработал. Вот мое решение.

Я хотел создать опрос с помощью кнопки Голосовать. Имя моего переключателя (ID) - PollGroupValue, а для Groupname установлено значение PollGroup в повторителе. Помните, атрибут Groupname в ASP.net отображается как атрибут name в сгенерированном html. Мой код выглядит следующим образом:

<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 меняет его, чтобы сделать его уникальным. Поэтому каждый переключатель получает различное имя группы (атрибут name в сгенерированной разметке на стороне клиента). Благодаря этому пользователь может выбрать все параметры одновременно. Эта проблема решается с помощью кода jquery, как объяснено в последующих комментариях.

Шаг 2: Этот блок кода создает новый атрибут custome с именем ci-name и копирует исходное значение атрибута name в этот новый настраиваемый атрибут. Этот процесс повторяется для каждого переключателя в опросе. Этот шаг поможет нам в следующем шаге.

Шаг 3: Этот блок кода устанавливает значение атрибутов имени всех переключателей в опросе равным значению атрибута имени первого переключателя. Этот шаг не позволяет пользователю выбирать более одной опции одновременно.

Шаг 4: Этот код в обработчике события нажатия кнопки голосования проверяет, выбрал ли пользователь хотя бы один параметр. Если нет, отображается сообщение об ошибке.

Шаг 5: Этот код внутри обработчика события нажатия кнопки голосования устанавливает значение атрибута name всех переключателей в исходное значение. Это достигается путем копирования значения из пользовательского атрибута ci-name. Это позволяет коду на стороне сервера asp.net узнать, какая кнопка была нажата.

2 голосов
/ 22 января 2013

Создание пользовательского элемента управления и переопределение UniqueID для просмотра списка 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. Чтобы сохранить имя уникальным для других элементов управления на странице (вне списка), вы можете получить UniqueId из ListView, добавить к нему GroupName и добавить его в RadioButton.

Это исправило проблему с группировкой радиокнопок в разных строках в виде списка. Возможно, вы захотите добавить еще немного логики со свойством, чтобы включить или выключить эту функцию, чтобы она работала как обычный RadioButton.

2 голосов
/ 07 декабря 2011

Вот чистое решение 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>
1 голос
/ 22 декабря 2015

Это чисто серверный подход с использованием отражения. Элемент управления RadioButton использует свойство UniqueGroupName для определения имени группы. Имя группы кэшируется в поле _uniqueGroupName. Установив это поле с помощью отражения, мы можем переопределить имя группы по умолчанию и использовать имя группы, одинаковое для всех переключателей в повторителе. Обратите внимание, что этот код должен быть запущен в событии «PreRender» элемента управления «RadioButton», чтобы новое имя группы сохранялось при отправке сообщений.

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

RadioButton исходный код: http://reflector.webtropy.com/default.aspx/Net/Net/3@5@50727@3053/DEVDIV/depot/DevDiv/releases/whidbey/netfxsp/ndp/fx/src/xsp/System/Web/UI/WebControls/RadioButton@cs/2/RadioButton@cs

...