2011-01-28 9 views
5

編集可能なコントロールコレクションを構築できる複合ASP.NETコントロールを作成しようとしています。ASP.NETダイナミックコントロールカウント(コントロールの作成)

私の問題は、フォームまたはポストバックボタン以外を押さないと、テキストボックスに入力された値が失われるということです。

ポストバックの間にコントロールの数が変更された場合、動作させることができません。基本的には、ビューの状態プロパティーControlCountに応じて、コントロールライフサイクルの2つの異なる時間にコントロールツリーを再作成する必要があります。

このテストでは、問題を再現するために使用することができます。

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リフレクターは何年も私の先生されています!)んと同じように、それによってバックアッププロパティを宣言することです。この方法では、イベントのライフサイクル中に自然に読み込まれ、保存されます。ここで

は、任意のトリックなしで、ごく自然に、あなたがやりたいように見えるコードです:

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の場合、それはうまくいきます。私はこの –

+0

について興味がありました。すべての 'textboxes'がポストバックが発生するたびにゼロから再度追加されたので、どのようにテキスト値を復元するのでしょうか?線量asp.netはsthでしたか? –

+0

@ラミー - はい、それはViewstateの魔法です。それはうまく動く:-) –

-2

私はあなたがビューステートにコントロールを追加するために持っていると信じています。

+0

いいえ、それはそのように動作しませんです。これは別のものです。特定のライフサイクルイベントが2回目に実行されていません(コントロールツリーが再作成されているため)。 –