2011-04-26 53 views
7
<asp:Button onclick="Some_event" Text="Add TextBox" ID="id1" runat="server" /> 
//once clicked: 
<asp:TextBox ID="txt1" ......></asp:TextBox> 
//when clicked again: 
<asp:TextBox ID="txt1" ......></asp:TextBox> 
<asp:TextBox ID="txt2" ......></asp:TextBox> 
//and so on... 

有沒有一種方法可以創建動態控件,即使在回發之後這些動態控件也會持續存在?換句話說,當用戶點擊按鈕時,將生成一個新的文本框,當再次點擊時,第一個將保留,而第二個將生成。我如何使用asp.net做到這一點?我知道,如果我可以在page_init事件中創建控件,那麼它們將持續存在,但我不知道是否有可能在page_init發生之前處理按鈕單擊,因此必須有其他方法。ASP.Net中的持久動態控制

+0

控件*必須*在回發時重新創建。但是,有些項目會自動執行此任務,例如[DynamicControlPlaceholder](http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx)(它會持續存在,然後再重新創建控件)。 – 2011-04-28 04:48:45

+0

是的,我已閱讀過關於它,但我想學習這東西:) – Shaokan 2011-04-28 10:05:02

回答

4

是的,這是可能的。一種使用純粹ASP.NET(這看起來像你所要求的)做到這一點的方法是保持已添加的TextBox控件的計數(將該值存儲在ViewState中),並重新創建TextBox控件。 Page_Load事件。當然,現今大多數人可能會使用JavaScript或jQuery來處理此任務的客戶端,但我把一個簡單的例子來演示如何與回傳工作:

頭版:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicControls.aspx.cs" Inherits="MyAspnetApp.DynamicControls" EnableViewState="true" %> 
<!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 runat="server"></head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:Button ID="btnAddTextBox" runat="server" Text="Add" OnClick="btnAddTextBox_Click" /> 
     <asp:Button ID="btnWriteValues" runat="server" Text="Write" OnClick="btnWriteValues_Click" /> 
     <asp:PlaceHolder ID="phControls" runat="server" /> 
    </div> 
    </form> 
</body> 
</html> 

代碼背後:

using System; 
using System.Web.UI.WebControls; 

namespace MyAspnetApp 
{ 
    public partial class DynamicControls : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      //Recreate textbox controls 
      if(Page.IsPostBack) 
      { 
       for (var i = 0; i < TextBoxCount; i++) 
        AddTextBox(i); 
      } 
     } 

     private int TextBoxCount 
     { 
      get 
      { 
       var count = ViewState["txtBoxCount"]; 
       return (count == null) ? 0 : (int) count; 
      } 
      set { ViewState["txtBoxCount"] = value; } 
     } 

     private void AddTextBox(int index) 
     { 
      var txt = new TextBox {ID = string.Concat("txtDynamic", index)}; 
      txt.Style.Add("display", "block"); 
      phControls.Controls.Add(txt); 
     } 

     protected void btnAddTextBox_Click(object sender, EventArgs e) 
     { 
      AddTextBox(TextBoxCount); 
      TextBoxCount++; 
     } 

     protected void btnWriteValues_Click(object sender, EventArgs e) 
     { 
      foreach(var control in phControls.Controls) 
      { 
       var textBox = control as TextBox; 
       if (textBox == null) continue; 
       Response.Write(string.Concat(textBox.Text, "<br />")); 
      } 
     } 
    } 
} 

由於您正在重新創建每個回發的控件,輸入到文本框中的值將在每個回發中保留。我添加了btnWriteValues_Click以快速演示如何從文本框中讀取值。

EDIT
我更新的例子添加包含一個文本框和一個刪除按鈕的面板。這裏的訣竅是Remove按鈕不會刪除容器面板,它只是使其不可見。這樣做是爲了使所有的控件ID保持不變,因此輸入的數據保留在每個文本框中。如果我們完全刪除TextBox,那麼刪除TextBox後的數據將在下一個回傳中向下移動一個TextBox(只是爲了更清楚地解釋這一點,如果我們有txt1,txt2和txt3,並刪除txt2,在下一個回傳中,我們將創建兩個文本框txt1和txt2,並且txt3中的值將丟失)。

public partial class DynamicControls : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (Page.IsPostBack) 
     { 
      for (var i = 0; i < TextBoxCount; i++) 
       AddTextBox(i); 
     } 
    } 

    protected void btnAddTextBox_Click(object sender, EventArgs e) 
    { 
     AddTextBox(TextBoxCount); 
     TextBoxCount++; 
    } 

    protected void btnWriteValues_Click(object sender, EventArgs e) 
    { 
     foreach(var control in phControls.Controls) 
     { 
      var panel = control as Panel; 
      if (panel == null || !panel.Visible) continue; 
      foreach (var control2 in panel.Controls) 
      { 
       var textBox = control2 as TextBox; 
       if (textBox == null) continue; 
       Response.Write(string.Concat(textBox.Text, "<br />")); 
      } 
     } 
    } 

    private int TextBoxCount 
    { 
     get 
     { 
      var count = ViewState["txtBoxCount"]; 
      return (count == null) ? 0 : (int) count; 
     } 
     set { ViewState["txtBoxCount"] = value; } 
    } 

    private void AddTextBox(int index) 
    { 
     var panel = new Panel(); 
     panel.Controls.Add(new TextBox {ID = string.Concat("txtDynamic", index)}); 
     var btn = new Button { Text="Remove" }; 
     btn.Click += btnRemove_Click; 
     panel.Controls.Add(btn); 
     phControls.Controls.Add(panel); 
    } 

    private void btnRemove_Click(object sender, EventArgs e) 
    { 
     var btnRemove = sender as Button; 
     if (btnRemove == null) return; 
     btnRemove.Parent.Visible = false; 
    } 
} 
+0

感謝很多老兄!這就是我一直在尋找的! – Shaokan 2011-04-27 10:54:07

+0

很高興我能幫到你。 – rsbarro 2011-04-27 13:55:25

+0

如果我想刪除動態文本框呢?我插入一個按鈕並在創建文本框時爲其分配一個事件。實際上,在第一次單擊文本框被成功刪除,但然後可能會發生一些錯誤(不是例外,但例如教科書的價值不會保存點擊)。有沒有簡單的方法來刪除指定的文本框? – Shaokan 2011-04-27 17:09:52

1

我讀了一篇由Scott Mitchell撰寫的文章,它解釋了ViewState只是在回發後持續改變控制狀態,而不是實際的控件本身。我沒有確切的場景,但我正在開發的一個項目需要動態添加用戶控件,並且我必須在每次回發中添加它們。在這種情況下,在Init中創建它們仍然有用,這樣它們可以保留它們的狀態。這裏是鏈接:Understanding ASP.NET View State。選中「查看狀態和動態添加的控件」部分。

您可能需要跟蹤所添加的所有控件(例如會話狀態),並在回發時重新創建它們。我只是做了一個小測試,我在Session中保留了所有Textbox ID的List<string>。回發時,我重新創建所有的文本框。

+0

非常感謝!猜我在度假時有很多要讀的東西:) – Shaokan 2011-04-27 10:55:15