2009-02-16 5 views
13

Ho il seguente codice molto sempliceAggiunta di controlli in modo dinamico ad un UpdatePanel in ASP.NET AJAX

<asp:ScriptManager ID="ScriptManager1" runat="server"> 
</asp:ScriptManager> 

<asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
<ContentTemplate> 
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"> 
    </asp:PlaceHolder> 
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /> 
</ContentTemplate> 
</asp:UpdatePanel> 

E codebehind

protected void Button1_Click(object sender, EventArgs e) 
{ 
    Literal literal = new Literal(); 
    literal.Text = DateTime.Now.ToString(); 
    literal.ID = DateTime.Now.Ticks.ToString(); 

    // These both work fine the first time the button is clicked 
    // but the second time nothing is added. 
    UpdatePanel1.ContentTemplateContainer.Controls.Add(literal); 
    PlaceHolder1.Controls.Add(literal); 
} 

Il mio problema arriva che il controllo letterale è sempre e solo aggiunto una volta. Ho perlustrato google e blog (più libri) ma senza fortuna. Cosa mi manca?

risposta

22

In asp.net, i controlli nel file ASPX vengono generati automaticamente su ogni postback. I controlli che hai creato non sono nel codice ASPX, quindi il framework non li crea per te. La prima volta che si esegue il metodo Button1_Click, si aggiunge un controllo aggiuntivo alla pagina. La seconda volta che esegui il metodo Button1_Click, sei su un altro post e quel primo pulsante extra è stato dimenticato. Quindi il risultato di questo postback è che ottieni di nuovo un pulsante in più.

Questo creerà un controllo in più ogni volta che si fa clic sul pulsante (anche se i timestamp aggiorneranno ogni volta che si preme il pulsante perché i controlli vengono ricreati)

protected void Button1_Click(object sender, EventArgs e) 
{ 
    int count = 0; 

    if (ViewState["ButtonCount"] != null) 
    { 
     count = (int)ViewState["ButtonCount"]; 
    } 

    count++; 
    ViewState["ButtonCount"] = count; 

    for (int i = 0; i < count; i++) 
    { 
     Literal literal = new Literal(); 
     literal.Text = DateTime.Now.ToString(); 
     literal.ID = DateTime.Now.Ticks.ToString(); 

     UpdatePanel1.ContentTemplateContainer.Controls.Add(literal); 
     PlaceHolder1.Controls.Add(literal); 
    }    
} 
+0

Esattamente quello che cercavo, grazie –

1

Accetto la risposta di cui sopra Tuttavia, questo approccio non salverà lo stato dei controlli dinamici (o per essere precisi, salverà lo stato ma non li caricherà di nuovo). Lo stato di caricamento del carico viene richiamato nella sezione Carica evento del ciclo di vita della pagina, in cui assegna indietro i valori di controllo salvati nello stato di visualizzazione. Tuttavia, se i controlli non vengono creati in questo momento, non possono essere caricati con dati precedenti, quindi affinché lo stato venga mantenuto, i nuovi controlli devono essere ricreati prima o durante l'evento di caricamento.

protected void Page_Load(object sender, EventArgs e) 
{ 
    //PS: Below approach saves state as id is constant, it simply generates a new control with same id hence viewstate loads the value 
    if (IsPostBack) 
    { 
     int count = 0; 

     if (ViewState["ButtonCount"] != null) 
     { 
      count = (int)ViewState["ButtonCount"]; 
     } 

     count++; 
     ViewState["ButtonCount"] = count; 

     for (int i = 0; i < count; i++) 
     { 
      TextBox literal = new TextBox(); 
      //literal.Text = DateTime.Now.ToString(); 
      literal.ID = "Textbox" + i.ToString(); 

      //UpdatePanel1.ContentTemplateContainer.Controls.Add(literal); 
      PlaceHolder1.Controls.Add(literal); 

     } 
    } 
} 

Dynamically adding controls View State and postback

+1

D'accordo, questo è meglio. Mantenere lo stesso ID attraverso i postback consente al viewstate di applicare correttamente. Comunque, questo dovrebbe essere fatto in Init della pagina come http://msdn.microsoft.com/en-us/library/ms972976.aspx –