ASP.NET: ¿Cómo acceder a los elementos de entrada de formulario generados por el repetidor?

StackOverflow https://stackoverflow.com/questions/179938

  •  05-07-2019
  •  | 
  •  

Pregunta

Quiero que un repetidor genere un montón de casillas de verificación, por ejemplo:

<tr><td><input type="checkbox" name="t" value="11cbf4deb87" /> <input type="checkbox" name="a" value="33cbf4deb87" />stackoverflow.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cbf4deb88" /> <input type="checkbox" name="a" value="33cbf4deb87" />microsoft.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cd3f33a89" /> <input type="checkbox" name="a" value="33cbf4deb87" />gmail.com</td></tr>
<tr><td><input type="checkbox" name="t" value="1138fecd337" /> <input type="checkbox" name="a" value="33cbf4deb87" />youporn.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11009efdacc" /> <input type="checkbox" name="a" value="33bf4deb87" />fantasti.cc</td></tr>

Pregunta 1: ¿Cómo hago referencia individualmente a cada casilla de verificación cuando el repetidor se está ejecutando para poder establecer el valor único?

¿Lo enlazo a datos con algo como:

<itemtemplate>
   <tr>
      <td>
         <input type="checkbox" name="t" 
            value="<%# ((Item)Container.DataItem).TangoUniquifier %>" />
         <input type="checkbox" name="a" 
            value="<%# ((Item)Container.DataItem).AlphaUniquifier %>" />
         <%# ((Item)Container.DataItem).SiteName %>
      </td>
   </tr>
</itemtemplate>

¿O se supone que debo configurarlo de alguna manera en OnItemDataBound?

<asp:repeater id="ItemsRepeater" 
      OnItemDataBound="ItemsRepeater_OnItemDataBound" runat="server">
   ...
   <itemtemplate>
      <tr>
         <td>
            <input id="chkTango" type="checkbox" name="t" runat="server" />
            <input id="chkAlpha" type="checkbox" name="a" runat="server" />
            <%# ((Item)Container.DataItem).SiteName %>
         </td>
      </tr>
   </itemtemplate>
   ...
</asp:repeater>


protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
   // if the data bound item is an item or alternating item (not the header etc)
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
   {
      // get the associated item
      Item item = (Item)e.Item.DataItem;

      //???
      this.chkTango.Value = item.TangoUniquifier;
      this.chkAlpha.Value = item.AlphaUniquifier;
   }
}

Pero si se supone que debo hacer referencia en el código subyacente, ¿cómo lo hago en el código subyacente? ¿Se supone que debo hacer referencia a él usando la propiedad de identificación (del lado del servidor) de un control <INPUT>? me doy cuenta de que la ID de un control en el lado del servidor no es la misma que la ID que estará presente en el cliente.

¿O tengo que hacer algo donde tengo que encontrar un control INPUT con un nombre de " t " y otro con un nombre de " a " ;? ¿Y qué tipo de control es un CheckBox que me permite establecer su valor de entrada?

protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
   // if the data bound item is an item or alternating item (not the header etc)
   if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
   {
      // get the associated item
      Item item = (Item)e.Item.DataItem;

      CheckBox chkTango = (CheckBox)e.Item.FindControl("chkTango");
      chkTango.Value = item.TangoUniquifier;

      CheckBox chkAlpha = (CheckBox)e.Item.FindControl("chkAlpha");
      chkAlpha.Value = item.AlphaUniquifier;
   }
}

Pregunta 2: Cuando el usuario luego haga clic en ENVIAR, ¿cómo encuentro todas las casillas marcadas, o más específicamente sus VALORES?

¿Tengo que encontrar FindControl?

protected void DoStuffWithLinks_Click(object sender, EventArgs e)
{
   // loop through the repeater items
   foreach (RepeaterItem repeaterItem in actionItemRepeater.Items)
   {
      Item item = repeaterItem.DataItem as Item;

      // grab the checkboxes
      CheckBox chkAlpha = (CheckBox)repeaterItem.FindControl("chkAlpha");
      CheckBox chkTango = (CheckBox)repeaterItem.FindControl("chkTango");

      if (chkAlpha.Checked)
      {          
         item.DoAlphaStuff(chkAlpha.Name);
      }

      if (chkTango.Checked)
      {
         item.DoTangoStuff(chkTango.Name);
      }
   }
}

¿Los elementos repetidores DataItem todavía están allí en un controlador de eventos de clic?

¿Fue útil?

Solución

Use el control del servidor en lugar de hacer un control de entrada runat = server

 <asp:CheckBox id="whatever" runat="Server" />

Cuando establece el valor en su ItemDataBound, usa FindControl

CheckBox checkBox = (CheckBox)e.Item.FindControl("whatever");
checkBox.Checked = true;

Cuando obtienes los elementos, también usas FindControl del elemento en una construcción foreach. Además, dependiendo de cómo lo vincules, el DataItem ya no estará allí después de una devolución de datos.

foreach (RepeaterItem item in myRepeater.Items)
{
    if (item.ItemType == ListItemType.Item 
        || item.ItemType == ListItemType.AlternatingItem) 
    { 
        CheckBox checkBox = (CheckBox)item.FindControl("whatever");
        if (checkBox.Checked)
        { /* do something */ }
    }
}
  • Muchas personas se sienten tentadas a 'lanzar de forma segura' utilizando el operador as con FindControl(). No me gusta eso porque cuando cambias el nombre del control en el formulario, puedes ignorar silenciosamente un error de desarrollo y hacer que sea más difícil de rastrear. Intento usar el operador <=> solo si no se garantiza que el control esté allí.

Actualización para: ¿Qué casilla de verificación es cuál? En el html procesado terminarás teniendo todos estos nombres de casilla de verificación como

ctl00_cph0_ParentContainer_MyRepeater_ctl01_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl02_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl03_MyCheckbox

No te importan los nombres porque el elemento foreach.FindControl () los obtiene para ti, y no debes asumir nada sobre ellos. Sin embargo, cuando itera a través de foreach, generalmente necesita una forma de hacer referencia a algo. La mayoría de las veces esto se hace al tener también un control asp: HiddenField junto con cada CheckBox para mantener un identificador que coincida con la entidad correcta.

Nota de seguridad : hay un problema de seguridad con el uso de campos ocultos porque un campo oculto puede modificarse en javascript; siempre tenga en cuenta que este valor podría haber sido modificado por el usuario antes de enviar el formulario.

Otros consejos

Puede resultarle más fácil usar un control CheckBoxList.

En el caso simple, configuraría el DataTextVield y el DataValueField con el nombre y el valor extraídos de su fuente de datos (suponiendo que esté poblando desde una fuente de datos) y luego vincúlelos para crear los elementos.

Probablemente menos trabajo de su parte que crear las casillas de verificación en un repetidor.

Aquí hay un código específico sobre cómo manejar el campo oculto:

MARKUP:

<asp:HiddenField ID="repeaterhidden" Value='<%# DataBinder.Eval(Container.DataItem, "value")%>' runat="server" >

C #:

{

HiddenField hiddenField = (HiddenField)item.FindControl(repeaterStringhidden);

{ /* do something with hiddenField.Value */

}

Creo que este KB me dio la mejor respuesta:

http://msdn.microsoft.com/en-us/library/ 1d04y8ss.aspx

para mi propia falta de suerte, esto parece estar disponible solo para la versión .net 4.0 (y todavía estoy atascado en 3.5 SP1).

citando (negrita es mía):

  

Cuando un control está dentro de un control enlazado a datos que genera instancias repetidas del control, ASP.NET genera los valores UniqueID y ClientID para cada instancia del control. El valor UniqueID se genera combinando el valor UniqueID del contenedor de nombres, el valor de ID del control y un número secuencial. Este es el caso de controles como DataList, Repeater , GridView y ListView.

     

ASP.NET genera valores de ClientID de manera similar cuando la propiedad ClientIDMode se establece en AutoID. Esto puede dificultar la referencia del control en el script del cliente, porque normalmente no puede predecir los valores de los números secuenciales que se utilizan. Si desea acceder a los controles vinculados a datos desde el script del cliente, puede establecer la propiedad ClientIDMode en Predictable. Esto facilita la predicción de los valores de ClientID.

     

Cuando configura ClientIDMode en Predictable, también puede configurar la propiedad ClientIDRowSuffixDataKeys con el nombre de un campo de datos que sea único , como la clave principal en una tabla de base de datos. Esto hace que ASP.NET genere un ID de cliente que será más fácil de predecir y hacer referencia en la secuencia de comandos del cliente si puede predecir valores de clave de datos.

Entonces, en la versión 3.5, lo estoy haciendo usando campos ocultos:

    foreach (RepeaterItem item in rptClientes.Items)
    {
        Panel pnl = (Panel)item.FindControl("divCliente");
        Control c = pnl.FindControl("hdnID");
        if (c is HiddenField)
        {
            if (((HiddenField)c).Value == hdnClienteNome.Value)
                pnl.BackColor = System.Drawing.Color.Beige;
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top