2008-12-18 28 views
33

Obtuve un control de plantilla (un repetidor) que incluye texto y otro marcado. Cada elemento tiene un botón de radio asociado, lo que permite al usuario seleccionar UNO de los elementos creados por el repetidor.ASP.NET RadioButton jugando con el nombre (nombre de grupo)

El repetidor escribe el botón de radio estableciendo su identificación y nombre generado con la convención de nomenclatura de ASP.NET predeterminada, haciendo que cada radiobot sea un 'grupo' completo. Esto significa que todos los botones de radio son independientes entre sí, lo que desafortunadamente significa que puedo seleccionar todos los botones de radio al mismo tiempo. El botón de radio tiene el atributo inteligente 'nombre de grupo' utilizado para establecer un nombre común, por lo que se agrupan y, por lo tanto, deben ser dependientes (por lo que solo puedo seleccionar uno a la vez). El problema es que esto no funciona, el repetidor se asegura de que la identificación y, por lo tanto, el nombre (que controla la agrupación) sean diferentes.

Como uso un repetidor (podría haber sido una lista o cualquier otro control de datos con plantillas) no puedo usar RadioButtonList. Entonces, ¿dónde me deja eso?

Sé que he tenido este problema antes y lo he resuelto. Sé que casi todos los programadores ASP.NET deben haberlo tenido también, así que ¿por qué no puedo buscar en Google y encontrar una solución sólida al problema? Encontré soluciones para hacer cumplir la agrupación por JavaScript (¡feo!) O incluso para manejar los botones de radio como controles que no son del servidor, forzándome a hacer un Request.Form[name] para leer el estado. También intenté experimentar anulando el atributo de nombre en el evento PreRender - desafortunadamente, la página propietaria y la página maestra nuevamente anulan este nombre para reflejar el id/nombre completo, así que termino con el mismo resultado incorrecto.

Si no tienes una solución mejor que la que publiqué, aún así puedes publicar tus pensamientos, al menos sabré que mi amigo 'Jack' tiene razón sobre lo complicado que es a veces ASP.NET;)

+0

Ver: * [ERROR: Los botones de opción no son mutuamente excluyentes cuando se utiliza en un control de servidor Repeater] (http://support.microsoft.com/default.aspx?scid=kb; en-us; Q316495) *. Eso es simplemente una locura ... Es un error desde el framework 1.0, y tiene un gran impacto. Necesito heredar el botón de radio y anular un par de métodos para que funcione (para mi versión actual de ASP.NET). ¿Lo que da? –

Respuesta

7

Google-fu: asp.net radiobutton repeater problem

hecho una desafortunada consecuencia de la mutilación de Identificación. Mi idea sería crear o elegir uno de los muchos controles disponibles que agregan soporte para el mismo nombre en el cliente.

+0

Lamentablemente tienes razón, pero es un gran dolor. –

7

ASP.NET Tip: Uso de los controles RadioButton en un repetidor

Este es el código de la función 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; 
} 

El código está vinculado al repetidor a través del evento ItemDataBound. Para que funcione correctamente, necesita saber el nombre del control Repeater, así como el nombre de grupo que está asignando a RadioButtons. En este caso, estoy usando rptPortfolios como el nombre del repetidor, y las carteras como el nombre del 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/

+0

¡Gran solución! Funciona muy bien – Ricketts

4

Vladimir Smirnov ha creado ya un gran control personalizado que resuelve este problema . Hemos estado usando el GroupRadioButton en nuestros proyectos y ha estado funcionando perfectamente con botones de radio creados dentro de un repetidor y otros fuera del repetidor, todos ellos siendo parte del mismo grupo.

0

Puede que esta no sea la solución ideal para todos, pero hice lo siguiente con jQuery.

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

etc...

Luego incluyen el siguiente código en su página maestra. (o todas sus 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; 
     }); 
    } 
}); 

});

3

Esto podría ser un poco mejor ..

tengo un control de usuario que es esencialmente un conjunto de botones de radio dentro de un repetidor, cada instancia del control de usuario tiene una propiedad pública denominada FilterTitle, que es único para cada instancia.

añadir estas dos propiedades a su botón de radio reemplazando FilterTitle con su propio nombre de la propiedad pública

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

más simplemente ..

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

que utiliza secuencias de comandos de 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> 
+0

+1 para una solución increíble! –

+2

¡Ten cuidado! si utiliza esta solución, no podrá procesar los cambios de usuario en el código subyacente porque los pares de nombre/valor que espera el servidor nunca se modificarán. _i.e._ cualquier elemento marcado/desmarcado durante la carga de la página permanecerá marcado/desmarcado a pesar de las acciones del usuario. –

1

I También estaba desconcertado por este error y decidió simplemente dejar caer el repetidor a favor de buildin dinámicamente g una mesa con los controles adentro. En el control de usuario o en su página, sólo tiene que añadir los siguientes 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> 

A continuación, añada las filas de datos en el código detrás con botones de radio y otros controles necesarios. Por supuesto, puede hacer lo mismo con otros elementos como el DIV:

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

Pero que todavía esperan para el equipo de ASP.NET para moverse a solucionar este problema desafortunado con repetidores y vistas de lista. Todavía me gusta el control del repetidor y lo uso siempre que sea posible.

5

Sé que esta es una publicación anterior, pero esto es lo que terminé haciendo con una lista. Mi lista de lista está encuadernada en código VB detrás, así que no estoy seguro si esto funcionará bien con un repetidor, pero me imagino que podría ser similar.

Lo que hice fue manejar el evento OnCheckChanged de los botones de radio con una función que desmarcó cualquier otro botón de opción. Luego busqué el botón de opción seleccionado cuando navegué fuera de la página.

Esta solución evita JavaScript y jQuery, e ignora por completo el problema de GroupName. No es ideal, pero funciona como (I) esperado. Espero que sea útil para otros.

de marcado:

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 

Y luego, cuando el botón Enviar se hace clic en:

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

¡Buena solución! He estado buscando una solución que no requiera javascript y nunca pensé simplemente en deseleccionar todo el botón de radio 'OnCheckChanged'. ¡Aclamaciones! – Curt

2

he aquí una solución Javascript puro en aras de la exhaustividad.

Sólo añadir este atributo onclick a su elemento de RadioButton (sustituir NombreGrupo con NombreGrupo sus RadioButton 's):

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

para insertar esta Javascript en su 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> 
2

Crear una Control personalizado y anulación de UniqueID a la vista de lista ID única + nombre de grupo

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; 


     } 
    } 

} 
} 

Es un control personalizado que hereda de RadioButton (clase pública MYRADIOBUTTON: RadioButton). Si no haces nada en la clase obtienes un RadioButton normal. Al anular UniqueId, puede cambiar la lógica de cómo se representa el atributo de nombre. Para mantener el nombre exclusivo de otros controles en la página (fuera de la vista de lista), puede obtener UniqueId de ListView y agregar GroupName a eso y agregarlo al RadioButton.

Esto soluciona el problema con la agrupación de RadioButtons en filas diferentes en una vista de lista. Es posible que desee agregar algo más de lógica con una propiedad para activar/desactivar esta función, de modo que se comporte como un RadioButton normal.

+0

Alguna explicación de lo que está haciendo su código sería útil para los lectores futuros de esta respuesta –

+0

es la primera línea Crear un control personalizado e invalidar UniqueID en la lista uniqueID + GroupName –

2

Sé que esta pregunta es un poco antigua, pero creo que podría ayudar a alguien, por lo tanto, publicando mi solución a este problema.

Este problema tiene 2 partes:

  1. para evitar la selección de más de un botón de opción a la vez.
  2. Para saber qué botón de radio se hizo clic en el código del lado del servidor.

Tuve el problema similar con el botón de radio en el repetidor. Encontré solución parcial aquí: Simple fix for Radio Button controls in an ASP.NET Repeater using jQuery

Lea el artículo anterior para entender el problema. Remití este artículo y fue de gran ayuda. Como se mencionó anteriormente, este problema tiene dos partes, la primera es evitar la selección de más de un botón de radio a la vez. En segundo lugar, para saber en qué botón de radio se hizo clic en el código del lado del servidor. La solución publicada en el artículo anterior funcionó para mí solo para la primera parte. Sin embargo, el código escrito allí y las actualizaciones de la solución publicada allí no funcionaron para mí. Así que tuve que modificarlo un poco para que funcione. Aquí está mi solución.

Quería crear una encuesta con el botón Votar. El nombre de mi botón de radio (ID) es PollGroupValue con Groupname establecido en PollGroup en un repetidor. Recuerde que el atributo de nombre de grupo en ASP.net se representa como atributo de nombre en html generado. Mi código es el siguiente:

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

Paso 1: Cada vez que un botón de opción se utiliza en el repetidor, su nombre de grupo se cambia, ya que asp.net cambia con el fin de que sea único. Por lo tanto, cada botón de opción recibe un nombre de grupo diferente (atributo de nombre en el marcado generado por el lado del cliente). Debido a esto, el usuario puede seleccionar todas las opciones al mismo tiempo. Este problema se resuelve mediante el uso de código jquery como se explica en los comentarios posteriores.

Paso 2: Este bloque de código crea un nuevo atributo custome llamado ci-name y copia el valor original del atributo de nombre en este nuevo atributo personalizado.Este proceso se repite para cada botón de radio en la encuesta. Este paso nos ayudaría en el paso posterior.

Paso 3: Este bloque de código establece el valor de los atributos de nombre de todos los botones de opción encuestados en el valor del atributo de nombre del primer botón de opción. Este paso evita que el usuario seleccione más de una opción a la vez.

Paso 4: Este código dentro del evento del controlador de eventos del botón de votación haga clic en evento, comprueba si el usuario ha marcado al menos una opción. Si no lo hizo, se muestra un mensaje de error.

Paso 5: Este código dentro del evento del controlador de eventos del botón de votación, establece el valor del atributo de nombre de todos los botones de radio en sus valores originales. Esto se logra copiando el valor del atributo personalizado ci-name. Esto permite que el código del lado del servidor asp.net sepa en qué botón se hizo clic realmente.

1

Este es un enfoque puro del lado del servidor que utiliza la reflexión. El control RadioButton usa la propiedad UniqueGroupName para determinar el nombre del grupo. El nombre del grupo está en caché dentro del campo _uniqueGroupName. Al establecer este campo mediante la reflexión, podemos anular el nombre predeterminado del grupo y usar un nombre de grupo que sea el mismo en todos los botones de opción de un repetidor. Tenga en cuenta que este código se debe ejecutar en el evento 'PreRender' del control 'RadioButton' para asegurarse de que el nombre del nuevo grupo se mantenga en todas las publicaciones posteriores. código

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 fuente: http://reflector.webtropy.com/default.aspx/Net/Net/[email protected]@[email protected]/DEVDIV/depot/DevDiv/releases/whidbey/netfxsp/ndp/fx/src/xsp/System/Web/UI/WebControls/[email protected]/2/[email protected]

+0

¿Es correcto que al hacerlo evitará que ASP.NET observando el estado 'Comprobado' de RadioButton, y tendrá que verificar manualmente 'Request.Form' para su estado? –

0

un control personalizado/anulación para evitar el método HtmlInputControl.RenderAttributes() haciendo caso omiso de la propiedad RenderedNameAttribute:

/// <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(@" /"); 
    } 
} 
0

Solía ​​mismo Technic desmarcar otra radio con jquery A continuación, encontrará el código

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

y escritura abajo

function UnCheckRadio(obj) { 
      $('.radioShop input[type="radio"]').attr('checked', false); 
      $(obj).children().attr('checked', true); 
     } 
Cuestiones relacionadas