Pergunta

Recebi um controle modelo (um repetidor) listando algum texto e outra marcação. Cada item possui um radiobutão associado a ele, possibilitando ao usuário selecionar um dos itens criados pelo repetidor.

O repetidor escreve o Radiobutton definindo seu ID e nome gerado com a Convenção de Nomeação Padrão do ASP.NET, tornando cada radiobutton um 'grupo' completo. Isso significa que todos os radiobutões são independentes um do outro, o que, infelizmente, significa que posso selecionar todos os radiobutões ao mesmo tempo. O Radiobutton possui o atributo inteligente 'GroupName' usado para definir um nome comum, para que eles sejam agrupados e, portanto, dependam (para que eu possa selecionar apenas um de cada vez). O problema é: isso não funciona - o repetidor garante que o ID e, portanto, o nome (que controla o agrupamento) são diferentes.

Como eu uso um repetidor (poderia ter sido um ListView ou qualquer outro controle de banco de dados modificado), não posso usar a lista de radiobutton. Então, onde isso me deixa?

Eu sei que já tive esse problema antes e resolvi. Eu sei que quase todo programador ASP.NET deve ter tido isso também, então por que não consigo pesquisar no Google e encontrar uma solução sólida para o problema? Me deparei com soluções para aplicar o agrupamento por JavaScript (feio!) Ou mesmo para lidar com os radiobutões como controles não servidores, forçando-me a fazer um Request.Form[name] para ler o status. Eu também tentei experimentar o substituto do atributo de nome no PreRender Evento - Infelizmente, a página e a página principal possuem novamente esse nome para refletir o ID/nome completo, então acabo com o mesmo resultado errado.

Se você não tem uma solução melhor do que eu postei, ainda é muito bem -vindo a postar seus pensamentos - pelo menos vou saber que meu amigo 'Jack' está certo sobre o quão bagunçado asp.net às vezes é;)

Foi útil?

Solução

Google-fu: Problema de repetidor de radiobutton asp.net

De fato, uma conseqüência infeliz do idiota de identidade. Minha opinião seria criar um - ou escolher um dos muitos disponíveis - controle personalizado que adiciona suporte para o mesmo nome no cliente.

Outras dicas

ASP.NET DICA: Usando controles de radiobutton em um repetidor

Este é o código para a função 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;
}

O código está vinculado ao repetidor através do evento ItemDatabound. Para que funcione corretamente, você precisa saber o nome do controle do repetidor, bem como o nome do grupo que você está atribuindo aos Radiobuttons. Nesse caso, estou usando o RPTportfolios como o nome do repetidor e os portfólios como nome do grupo:

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/

Vladimir Smirnov já criou um ótimo controle personalizado que resolve esse problema. Temos usado o Groupradiobutton Em nossos projetos e tem funcionado perfeitamente com botões de rádio criados dentro de um repetidor e outros fora do repetidor, sendo parte do mesmo grupo.

Eu uso o script 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>

Sei que este é um post antigo, mas eis o que acabei fazendo com uma ListView. Meu ListView está vinculado no VB CodeBehind, então não tenho certeza se isso funcionará bem com um repetidor, mas imagino que possa ser semelhante.

O que eu fiz foi lidar com o evento OncheckChanged dos Radiobuttons com uma função que não selecionava outros botões de rádio. Então procurei o botão de rádio selecionado quando eu naveguei para longe da página.

Esta solução evita JavaScript e JQuery e ignora completamente a questão do nome do grupo. Não é o ideal, mas funciona como (i) esperava. Espero que seja útil para os outros.

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>

Código:

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

E então, quando o botão Enviar é clicado:

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

Isso pode ser um pouco melhor ..

Eu tenho um UserControl que é essencialmente um conjunto de radiobutões dentro de um repetidor, cada instância do UserControl possui uma propriedade pública chamada filterTitle, que é exclusiva por instância.

Adicione essas duas propriedades ao seu Radiobutton Substituindo o FilterTitle pelo seu próprio nome de propriedade pública

onclick='<%# "$(\"input[name$=btngroup_" + FilterTitle + "]\").removeAttr(\"checked\"); $(this).attr(\"checked\",\"checked\");" %>' GroupName='<%# "btngroup_" + FilterTitle  %>'

mais simplesmente..

onclick="$('input[name$=btngroup1]').removeAttr('checked'); $(this).attr('checked','checked');" GroupName="btngroup1"

Aqui está uma solução pura de JavaScript por uma questão de completude.

Basta adicionar isso onclick atribuir ao seu RadioButton elemento (substitua Nome do grupo com o seu RadioButtonGroupName):

<asp:RadioButton ... GroupName="GroupName" onclick="SelectRadioButton('GroupName$',this)" ... />

E inclua este JavaScript em sua página:

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

Crie um controle personalizado e substitua exclusivo para o 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;


        }
    }

}
}

É um controle personalizado que herda do Radiobutton (classe pública Myradiobutton: Radiobutton). Se você não faz nada na classe, recebe um radiobutton normal. Substituindo o únicoID, você pode alterar a lógica de como o atributo de nome é renderizado. Para ainda manter o nome exclusivo de outros controles na página (fora do ListView), você pode obter o únicoID do ListView e adicionar o nome do grupo a isso e adicioná -lo ao radiobutton.

Isso corrige o problema com o agrupamento de radiobutões em diferentes linhas em um ListView. Você pode adicionar mais lógica com uma propriedade para ativar/desativar esse recurso, para que ele se comporte como um radiobutton normal.

Sei que essa pergunta é um pouco velha, mas acho que pode ajudar alguém, postando minha solução para esse problema.

Este problema tem 2 partes:

  1. Para evitar a seleção de mais de um botão de rádio por vez.
  2. Para saber qual botão de rádio foi clicado no código do lado do servidor.

Eu tive o problema semelhante com o botão de rádio no repetidor. Encontrei solução parcial aqui:Fix simples para controles de botão de rádio em um repetidor de asp.net usando jQuery

Leia o artigo acima para entender o problema. Referi este artigo e foi uma boa ajuda. Como mencionado acima, esse problema tem duas partes, primeiro é impedir a seleção de mais de um botão de rádio por vez. Segundo, para saber qual botão de rádio foi clicado no código do lado do servidor. A solução publicada no artigo acima funcionou para mim apenas para a primeira parte. No entanto, o código escrito lá, bem como atualizações para a solução publicada, não funcionou para mim. Então, eu tive que modificá -lo um pouco para funcionar. Aqui está minha solução.

Eu queria criar enquete com o botão de voto. O nome do meu botão de rádio (ID) é PollGroupValue com o GroupName definido como PollGroup em um repetidor. Lembre -se de que o atributo GroupName no ASP.NET é renderizado como atributo de nome no HTML gerado. Meu código é o seguinte:

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

Etapa 1: Sempre que um botão de rádio é usado no repetidor, seu nome de grupo é alterado, pois o ASP.NET muda para torná -lo exclusivo. Portanto, cada botão de rádio obtém o nome de grupo diferente (atributo de nome na marcação gerada pelo cliente). Devido a isso, o usuário pode selecionar todas as opções ao mesmo tempo. Este problema é resolvido usando o código jQuery, conforme explicado pelos comentários subsequentes.

Etapa 2: Este bloco de código cria um novo atributo Custome chamado CI-name e copia o valor original do atributo de nome neste novo atributo personalizado. Esse processo se repete para cada botão de rádio na pesquisa. Esta etapa nos ajudaria em etapa posterior.

Etapa 3: Este bloco de código define o valor dos atributos de nome de todos os botões de rádio na pesquisa para o valor do atributo de nome do primeiro botão de rádio. Esta etapa impede que o usuário selecione mais de uma opção por vez.

Etapa 4: Este código Inside Event Handler Of Button CLIQUE DO EVENTO DE CLIQUE DA VOLTA Se o usuário verificou pelo menos uma opção. Se ele não tiver, uma mensagem de erro é mostrada.

Etapa 5: Este código Inside Event Handler Of Vote Button Click, define o valor do atributo de nome de todos os botões de rádio para seus valores originais. Isso é conseguido copiando o valor do atributo personalizado CI-name. Isso permite que o código lateral do servidor ASP.NET saiba qual botão foi realmente clicado.

Também fiquei perplexo com esse bug e decidi simplesmente deixar o repetidor em favor de construir dinamicamente uma mesa com os controles dentro. No seu controle do usuário ou na sua página, basta adicionar os seguintes elementos:

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

Em seguida, adicione as linhas de dados no código por trás dos botões de rádio e outros controles necessários. É claro que você pode fazer o mesmo com outros elementos como o div:

<div runat="server" ID=theDiv">
</div>

Mas ainda esperamos que a equipe do ASP.NET corra esse problema infeliz com repetidores e visualizações de listagem. Ainda gosto do controle do repetidor e o uso sempre que possível.

Esta é uma abordagem do lado do servidor puro usando a reflexão. o RadioButton Control usa o UniqueGroupName propriedade para determinar o nome do grupo. O nome do grupo é armazenado em cache dentro do _uniqueGroupName campo. Ao definir esse campo usando a reflexão, podemos substituir o nome do grupo padrão e usar um nome de grupo que é o mesmo em todos os botões de rádio em um repetidor. Observe que este código deve ser executado no evento 'Prerender' do controle 'Radiobutton' para garantir que o novo nome do grupo seja persistido nas postagens.

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 Código fonte: http://reflector.webtropy.com/default.aspx/net/net/3@5@50727@3053/devdiv/depot/devdiv/releases/whidbey/netfxsp/ndp/fx/src/xspspstem/web/web/weby/netfxsp/ndp/fx/src/xspspstem/web/web/web/webe UI/webcontrols/radiobutton@cs/2/radiobutton@cs

Esta pode não ser a solução ideal para todos, mas fiz o seguinte usando o jQuery.

<asp:RadioButton ID="rbtnButton1" groupName="Group1" runat="server" /> <asp:RadioButton ID="rbtnButton2" groupName="Group1" runat="server" />

etc...

Em seguida, inclua o código a seguir em sua página mestre. (ou todas as suas páginas)

$(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;
        });
    }
});

});

Um controle/substituição personalizado para contornar o HtmlInputControl.RenderAttributes() método ignorando o RenderedNameAttribute propriedade:

/// <summary>
/// HACK:  For Microsoft&apos;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(@" /");
    }
}

Eu usei a mesma técnica para desmarcar outro rádio com jQuery, por favor, encontre o código abaixo

<asp:RadioButton ID="rbSelectShiptoShop" runat="server" onchange="UnCheckRadio(this);" CssClass="radioShop" />

e script abaixo

function UnCheckRadio(obj) {
           $('.radioShop input[type="radio"]').attr('checked', false);
           $(obj).children().attr('checked', true);
       }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top