ASP.NET: Come accedere agli elementi di input del modulo generati dal ripetitore?

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

  •  05-07-2019
  •  | 
  •  

Domanda

Voglio che un ripetitore generi un sacco di caselle di controllo, ad esempio:

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

Domanda 1: Come posso fare riferimento individualmente a ciascuna casella di controllo quando il ripetitore è in esecuzione in modo da poter impostare il valore univoco?

Posso collegarli ai dati con qualcosa del tipo:

<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 dovrei impostarlo in qualche modo in 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;
   }
}

Ma se devo fare riferimento nel code-behind, come posso fare riferimento nel code-behind? Devo fare riferimento a esso usando la proprietà id (lato server) di un controllo <INPUT>? mi rendo conto che l'ID di un controllo sul lato server non è lo stesso dell'ID che sarà presente sul client.

O devo fare qualcosa in cui devo trovare un controllo INPUT con un nome di " t " e un altro con un nome di " a " ;? E che tipo di controllo è un CheckBox che mi consente di impostare il suo valore di input?

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

Domanda 2: Quando in seguito l'utente fa clic su INVIA, come posso trovare tutte le caselle di controllo selezionate o, più specificamente, i loro VALORI?

Devo trovare 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);
      }
   }
}

Gli elementi ripetitori DataItem sono ancora presenti su un gestore eventi click?

È stato utile?

Soluzione

Utilizza il controllo server invece di eseguire un controllo di input runat = server

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

Quando si imposta il valore in ItemDataBound, si utilizza FindControl

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

Quando ottieni gli oggetti, usi anche FindControl dall'elemento in un costrutto foreach. Inoltre, a seconda di come lo si inserisce nel database, DataItem potrebbe non essere più presente dopo un postback.

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 */ }
    }
}
  • Molte persone sono tentate di "trasmettere in sicurezza" utilizzando l'operatore as con FindControl(). Non mi piace perché quando si modifica il nome del controllo nel modulo, è possibile ignorare silenziosamente un errore di sviluppo e rendere più difficile la ricerca. Cerco di utilizzare l'operatore <=> solo se il controllo non è garantito.

Aggiornamento per: Quale CheckBox è quale? Nel codice HTML renderizzato finirai per avere tutti questi nomi come

ctl00_cph0_ParentContainer_MyRepeater_ctl01_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl02_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl03_MyCheckbox

Non ti importa quali sono i nomi perché foreach item.FindControl () li ottiene per te e non dovresti assumere nulla a riguardo. Tuttavia, quando si esegue l'iterazione tramite foreach, di solito è necessario un modo per fare riferimento a qualcosa. Il più delle volte ciò avviene anche con un asp: controllo HiddenField accanto a ciascun CheckBox per contenere un identificatore per far corrispondere l'entità corretta.

Nota di sicurezza : esiste un problema di sicurezza nell'uso dei campi nascosti perché un campo nascosto può essere modificato in javascript; tenere sempre presente che questo valore avrebbe potuto essere modificato dall'utente prima dell'invio del modulo.

Altri suggerimenti

Potrebbe essere più semplice utilizzare un controllo CheckBoxList.

Nel caso semplice, imposta DataTextVield e DataValueField sul nome e sul valore estratti dall'origine dati (supponendo che stai popolando da un'origine dati) e quindi lo associ per creare gli elementi.

Probabilmente meno lavoro da parte tua rispetto alla creazione delle caselle di controllo in un ripetitore.

Ecco un codice specifico per come gestire il campo nascosto:

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

}

Credo che questo KB mi abbia dato la risposta migliore:

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

per mia sfortuna, questo sembra essere disponibile solo per la versione .net 4.0 (e sono ancora bloccato su 3.5 SP1).

citazione (grassetto è mio):

  

Quando un controllo si trova all'interno di un controllo con associazione a dati che genera istanze ripetute del controllo, ASP.NET genera valori UniqueID e ClientID per ciascuna istanza del controllo. Il valore UniqueID viene generato combinando il valore UniqueID del contenitore di denominazione, il valore ID del controllo e un numero sequenziale. Questo è il caso di controlli come DataList, Repeater , GridView e ListView.

     

ASP.NET genera i valori ClientID in modo simile quando la proprietà ClientIDMode è impostata su AutoID. Ciò può rendere difficile fare riferimento al controllo nello script client, poiché in genere non è possibile prevedere i valori dei numeri sequenziali utilizzati. Se desideri accedere ai controlli associati ai dati dallo script client, puoi impostare la proprietà ClientIDMode su Predictable. Ciò semplifica la previsione dei valori di ClientID.

     

Quando si imposta ClientIDMode su Predictable, è anche possibile impostare la proprietà ClientIDRowSuffixDataKeys sul nome di un campo dati univoco , ad esempio la chiave primaria in una tabella del database. In questo modo ASP.NET genera un ID client che sarà più facile da prevedere e fare riferimento nello script client se è possibile prevedere i valori della chiave dei dati.

Quindi, nella versione 3.5, lo sto facendo usando campi nascosti:

    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;
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top