2011-01-28 13 views
5

Sto provando a creare un controllo ASP.NET composito che consente di creare una raccolta di controlli modificabile.Conteggi di controlli dinamici ASP.NET (creazione di controlli man mano che si procede)

Il mio problema è che quando premo il pulsante aggiungi o postback (che non fa altro che postback del modulo) tutti i valori immessi nelle caselle di testo vanno perduti.

Non riesco a farlo funzionare quando il numero di controlli cambia tra i postback. Devo essere fondamentalmente in grado di ricreare l'albero di controllo in due momenti diversi nel ciclo di vita del controllo a seconda della proprietà dello stato di visualizzazione ControlCount.

Questo test può essere utilizzato per riprodurre il problema:

public class AddManyControl : CompositeControl 
{ 
    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 
     EnsureChildControls(); 
    } 

    protected override void CreateChildControls() 
    { 
     var count = ViewState["ControlCount"] as int? ?? 0; 

     for (int i = 0; i < count; i++) 
     { 
      var div = new HtmlGenericControl("div"); 
      var textBox = new TextBox(); 
      textBox.ID = "tb" + i; 
      div.Controls.Add(textBox); 
      Controls.Add(div); 
     } 

     ViewState["ControlCount"] = count; 

     var btnAdd = new Button(); 
     btnAdd.ID = "Add"; 
     btnAdd.Text = "Add text box"; 
     btnAdd.Click += new EventHandler(btnAdd_Click); 
     Controls.Add(btnAdd); 

     var btnPostBack = new Button(); 
     btnPostBack.ID = "PostBack"; 
     btnPostBack.Text = "Do PostBack"; 
     Controls.Add(btnPostBack); 
    } 

    void btnAdd_Click(object sender, EventArgs e) 
    { 
     ViewState["ControlCount"] = (int)ViewState["ControlCount"] + 1; 
    } 

    protected override void OnPreRender(EventArgs e) 
    { 
     base.OnPreRender(e); 
     // If I remove this RecreateChildControls call 
     // the collection lags behind each postback 
     // because the count is incremented in the btnAdd_Click event handler 
     // however, the values are not lost between postbacks 
     RecreateChildControls(); 
    } 
} 

risposta

5

Se si desidera giocare con i controlli personalizzati di ASP.NET, è necessario giocare secondo la sua regola e il suo schizzinoso! Quando inizi a giocare con OnPreRender in un controllo personalizzato, sai di essere sulla strada sbagliata il 90% delle volte.

In genere, il modo migliore per utilizzare ViewState è dichiarare una proprietà di cui è stato eseguito il backup, proprio come fanno i controlli ASP.NET standard (.NET Reflector è stato il mio insegnante per anni!). In questo modo, verrà letto e salvato in modo naturale durante il ciclo di vita dell'evento.

Qui è un codice che sembra fare quello che vuoi, tutto naturale, senza trucco:

public class AddManyControl : CompositeControl 
{ 
    private void AddControl(int index) 
    { 
     var div = new HtmlGenericControl("div"); 
     var textBox = new TextBox(); 
     textBox.ID = "tb" + index; 
     div.Controls.Add(textBox); 
     Controls.AddAt(index, div); 
    } 

    protected override void CreateChildControls() 
    { 
     for (int i = 0; i < ControlsCount; i++) 
     { 
      AddControl(i); 
     } 

     var btnAdd = new Button(); 
     btnAdd.ID = "Add"; 
     btnAdd.Text = "Add text box"; 
     btnAdd.Click += new EventHandler(btnAdd_Click); 
     Controls.Add(btnAdd); 

     var btnPostBack = new Button(); 
     btnPostBack.ID = "PostBack"; 
     btnPostBack.Text = "Do PostBack"; 
     Controls.Add(btnPostBack); 
    } 

    private int ControlsCount 
    { 
     get 
     { 
      object o = ViewState["ControlCount"]; 
      if (o != null) 
       return (int)o; 

      return 0; 
     } 
     set 
     { 
      ViewState["ControlCount"] = value; 
     } 
    } 

    void btnAdd_Click(object sender, EventArgs e) 
    { 
     int count = ControlsCount; 
     AddControl(count); 
     ControlsCount = count + 1; 
    } 
} 
+0

+1 per la soluzione, funziona benissimo, ero curioso di sapere questo –

+0

dato che tutte le 'textboxes' sono state aggiunte di nuovo ogni volta che il postback si accumula, come mai ripristinano i loro valori di testo? la dose che asp.net ha fatto sth? –

+0

@Rami - sì, questa è la magia di Viewstate, quando funziona bene :-) –

-2

credo che si deve aggiungere il controllo nello stato di visualizzazione.

+0

no, non è non funziona così. Questo è qualcos'altro. Alcuni eventi del ciclo di vita non vengono eseguiti la seconda volta (poiché l'albero dei controlli viene ricreato). –

Problemi correlati