2010-11-03 7 views
5

Desidero creare un controllo che consenta all'utente di progettare la propria struttura del sito Web. Ho immaginato che all'interno di UpdatePanel ci siano i controlli con TextBox (per il nome della pagina) e Button "aggiungi sotto". Sarebbe sembra:Controlli dinamici creati all'interno di UpdatePanel?

| "Questions" | 
| [ add below ] | 

|  "Tags" | 
| [ add below ] | 

| "Badges" | 
| [ add below ] | 

ora quando l'utente clicca sul pulsante nell'elemento "Tag" non deve apparire nuovo, tra il "Tag" e "badge", con il nome modificabile, così l'utente può nominarlo "Utenti" per esempio. Dovrebbe essere fatto senza postback completo (per evitare che la pagina lampeggi).

Ora è il mio problema: non posso (non finalmente tutti) caricare i controlli in onInit in quanto essi non esistono, ma devo partecipare alla loro clicca evento così dovrei allegando listener di eventi che cosa dovrebbe essere fatto durante Init fase. Come posso ottenere la funzionalità descritta?

Ho giocato per troppo tempo e sono confuso. Sarei grato per eventuali suggerimenti.

risposta

12

Questa è una situazione complicata perché hai a che fare con i controlli dinamici di cui hai bisogno per popolarli sulla pagina init per mantenere lo stato di visualizzazione, anche per gli annunci di controlli ded all'interno di un pannello di aggiornamento durante i clic del pulsante non sembra essere registrato fino al prossimo postback, quindi il normale evento di clic del pulsante si attiva solo una volta ogni volta che si fa clic su un controllo appena aggiunto. Potrebbe esserci un altro modo per ovviare a questo rispetto al modo in cui l'ho fatto. Se qualcuno sa che mi piacerebbe scoprirlo.

La mia soluzione è mantenere un elenco di ciò che è stato aggiunto dinamicamente e memorizzarlo in una variabile di sessione (perché il viewstate non è stato caricato durante la pagina init). Quindi sulla pagina init carica tutti i controlli che hai aggiunto in precedenza. Quindi gestisci l'evento click durante il caricamento della pagina con un codice personalizzato o il normale evento click.

Ho creato una pagina di esempio per testare questo.

Ecco il codice per la pagina aspx (default.aspx):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head id="Head1" runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> 
    <p>This only updates on full postbacks: <%= DateTime.Now.ToLongTimeString() %></p> 
    <asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
     <ContentTemplate> 
      <asp:PlaceHolder ID="PlaceholderControls" runat="server"></asp:PlaceHolder> 
     </ContentTemplate> 
    </asp:UpdatePanel> 
    </form> 
</body> 
</html> 

E qui è il codice per il codice sottostante pagina (default.aspx.cs):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

public partial class _Default : System.Web.UI.Page 
{ 
    /// <summary> 
    /// this is a list for storing the id's of dynamic controls 
    /// I have to put this in the session because the viewstate is not 
    /// loaded in the page init where we need to use it 
    /// </summary> 
    public List<string> DynamicControls 
    { 
     get 
     { 
      return (List<string>)Session["DynamicControls"]; 
     } 
     set 
     { 
      Session["DynamicControls"] = value; 
     } 
    } 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     PlaceholderControls.Controls.Clear(); 

     //add one button to top that will cause a full postback to test persisting values-- 
     Button btnFullPostback = new Button(); 
     btnFullPostback.Text = "Cause Full Postback"; 
     btnFullPostback.ID = "btnFullPostback"; 
     PlaceholderControls.Controls.Add(btnFullPostback); 

     PlaceholderControls.Controls.Add(new LiteralControl("<br />")); 

     PostBackTrigger FullPostbackTrigger = new PostBackTrigger(); 
     FullPostbackTrigger.ControlID = btnFullPostback.ID; 

     UpdatePanel1.Triggers.Add(FullPostbackTrigger); 
     //----------------------------------------------------------------------- 




     if (!IsPostBack) 
     { 
      //add the very first control   
      DynamicControls = new List<string>(); 

      //the DynamicControls list will persist because it is in the session 
      //the viewstate is not loaded yet 
      DynamicControls.Add(AddControls(NextControl)); 

     } 
     else 
     { 
      //we have to reload all the previously loaded controls so they 
      //will have been added to the page before the viewstate loads 
      //so their values will be persisted 
      for (int i = 0; i < DynamicControls.Count; i++) 
      { 
       AddControls(i); 
      } 
     } 


    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 

     if (!IsPostBack) 
     { 
      //we have to increment the initial 
      //control count here here be cause we cannot persit data in the viewstate during 
      //page init 

      NextControl++; 

     } 
     else 
     { 
      HandleAddNextClick();   

     } 

    } 

    /// <summary> 
    /// this function looks to see if the control which caused the postback was one of our 
    /// dynamically added buttons, we have to do this because the update panel seems to interefere 
    /// with the event handler registration. 
    /// </summary> 
    private void HandleAddNextClick() 
    { 
     //did any of our dynamic controls cause the postback if so then handle the event 
     if (Request.Form.AllKeys.Any(key => DynamicControls.Contains(key))) 
     { 
      DynamicControls.Add(AddControls(NextControl)); 
      NextControl++; 
     } 
    } 



    protected void btnAddNext_Command(object sender, CommandEventArgs e) 
    { 
     //this is intentionally left blank we are handling the click in the page load 
     //because the event for controls added dynamically in the click does 
     //not get registered until after a postback, so we have to handle it 
     //manually. I think this has something to do with the update panel, as it works 
     //when not using an update panel, there may be some other workaround I am not aware of 

    } 

    /// <summary> 
    /// variable for holding the number of the next control to be added 
    /// </summary> 
    public int NextControl 
    { 
     get 
     { 
      return ViewState["NextControl"] == null ? 0 : (int)ViewState["NextControl"]; 
     } 
     set 
     { 
      ViewState["NextControl"] = value; 
     } 
    } 


    /// <summary> 
    /// this function dynamically adds a text box, and a button to the placeholder 
    /// it returns the UniqueID of the button, which is later used to find out if the button 
    /// triggered a postback 
    /// </summary> 
    /// <param name="ControlNumber"></param> 
    /// <returns></returns> 
    private string AddControls(int ControlNumber) 
    { 
     //add textbox 
     TextBox txtValue = new TextBox(); 
     txtValue.ID = "txtValue" + ControlNumber; 
     PlaceholderControls.Controls.Add(txtValue); 

     //add button 
     Button btnAddNext = new Button(); 
     btnAddNext.Text = "Add Control " + ControlNumber; 
     btnAddNext.ID = "btnAddNext" + ControlNumber; 
     int NextControl = ControlNumber + 1; 
     btnAddNext.CommandArgument = NextControl.ToString(); 

     btnAddNext.Command += new CommandEventHandler(btnAddNext_Command); 
     PlaceholderControls.Controls.Add(btnAddNext); 

     //add a line break 
     PlaceholderControls.Controls.Add(new LiteralControl("<br />")); 

     return btnAddNext.UniqueID; 

    }  
} 

Fammi sapere se questo codice ti aiuta affatto. Ho provato ad aggiungere commenti con la mia comprensione di cosa sta succedendo e di come funziona.

+0

mi sarà sicuramente controllare la vostra soluzione dopo il lavoro e darti più feedback Molte grazie per il campione anche se non l'ho chiesto! – zgorawski

+0

Funziona come un incantesimo :) Ho dimenticato/non so di alcune funzionalità che hai usato, quindi la mia soluzione era incompleta. Grazie molto! Mi hai aiutato molto :) – zgorawski

+0

contento di aver potuto aiutarti, mi piacerebbe che ci fosse un modo per farlo senza usare la sessione, ma non conosco nessun altro modo semplice per archiviare e recuperare informazioni prima che il viewstate venga caricato. Probabilmente potresti usare campi o cookie nascosti, ma quelli sembrano come se portassero idee. Forse c'è un modo per caricare manualmente il viewstate e usarlo nella pagina init. –

-1

Se si vuole eventhandlers dinamici per i controlli, allora si può provare questo -

Considerando un controllo pulsante,

Button btnTest = new Button(); 
btnTest .Click += new EventHandler(btnTest_Click); 

si può avere il codice in caso pulsante di scatto,

void btnTest_Click(object sender, EventArgs e) 
{ 
    //your code 
} 
0

In questo modo lavorare per me

protected void Page_Load(object sender, EventArgs e) 
    { 
     if (Page.IsPostBack) 
     { 
      Button_Click(null, null); 
     } 
    } 

In chiamata pulsante

protected void Button_Click(object sender, EventArgs e) 
    { 
      Panel1.Controls.Clear(); 
      this.YourMethod(); 
     } 
    } 

Prima di chiamare il metodo Clear il controllo altrimenti caricare due volte

Problemi correlati