2011-01-28 69 views
5

我想創建一個複合ASP.NET控件,讓你建立一個可編輯的控件集合。ASP.NET動態控件計數(創建控件,你去)

我的問題是,當我按下添加或回發按鈕(除了要回發表單之外什麼都不做),任何輸入到文本框中的值都會丟失。

當控件的數量在回發之間發生變化時,我無法使它工作。我需要基本上能夠在控制生命週期的兩個不同時間重新創建控制樹,具體取決於視圖狀態屬性ControlCount

該測試可用於重現該問題:

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

回答

5

如果你想玩ASP.NET的自定義控件,你必須發揮它的規則和它的挑剔!當您開始在自定義控件中使用OnPreRender時,您會發現90%的時間都處於錯誤的軌道上。

一般來說,使用ViewState的最好方法是聲明一個由它支持的屬性,就像標準的ASP.NET控件一樣(.NET Reflector多年來一直是我的老師!)。這樣,它將在事件的生命週期中被自然地讀取和保存。

這裏,似乎你想要做什麼,很自然的一個代碼,沒有任何訣竅:

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爲解決方案,它工作正常,我很好奇 – 2011-01-30 13:45:36

-2

我相信你必須控制加入到視圖狀態。

+0

沒有,它不喜歡的工作。這是別的。某些生命週期事件沒有在第二次運行(因爲正在重新創建控制樹)。 – 2011-01-29 09:35:06