2010-11-18 169 views
15

我知道這個問題已經被問過幾千次了,之前我一直在努力,但由於某種原因,我無法完成我想完成的任務......我有一個動態添加的LinkBut​​ton,點擊後會動態添加一個控件(在本例中爲一個文本框)到同一個面板。其目的是不斷添加與LinkBut​​ton點擊次數相同的控件(即,我點擊一次,一個框,然後再次點擊會給我2個框,另一個點擊會添加一個第三個)。在下面的代碼中,我使用序列化的當前日期和時間爲每個文本框控件創建一個唯一的ID。ASP.NET動態創建控件和Postback

當我執行代碼時,單擊「添加過濾器」將會生成一個新的文本框,但是一旦再次單擊將創建一個新的文本框,並在其之前處理該文本框。相反,我想堅持以前的文本框以及其中提交的任何數據。

您的幫助表示讚賞。

在ASPX:

<asp:Panel ID="pnlFilter" runat="server"> 

</asp:Panel> 

在aspx.cs:

protected void Page_Init(object sender, EventArgs e) 
{ 
     LinkButton lb = new LinkButton(); 
     lb.ID = "lbAddFilter"; 
     pnlFilter.Controls.Add(lb); 
     lb.Text = "Add Filter"; 
     lb.Click += new EventHandler(lbAddFilter_Click); 
} 


void lbAddFilter_Click(object sender, EventArgs e) 
{ 
    TextBox tb = new TextBox(); 
    tb.ID = "tb" + DateTime.Now.ToBinary().ToString(); 
    pnlFilter.Controls.Add(tb); 
} 

回答

16

對於其他人試圖做這樣的事情:不要。相反,想一想信息流,並瞭解有更好的方法去做。輸入控件不需要動態創建。它們可以是靜態的,並且在填寫並提交時,該信息必須位於某處(例如數據庫,緩存,會話)。一旦它在那裏,回發,循環通過您的存儲選擇的所有項目,併爲他們創建一個顯示。

這就是我所做的,它使生活變得更加輕鬆。希望它能幫助別人。

+0

在某個應用程序中創建問卷(民意調查)並通過網絡服務 呈現的情況下,您會做什麼?網站會提取投票併爲其顯示字段? 在這種情況下動態創建內容是唯一合適的選項不是? – Sander 2011-05-31 09:14:26

+0

是的,動態創建內容是按順序的,但它不必像我試圖做的那樣是漸進的;我假設您的網絡服務每次都會返回所有結果,在這種情況下,您每次都會呈現所有結果。通過使用視圖狀態和緩存,你的表現應該很好。 – 2011-05-31 16:23:01

+1

你是個天才。我試圖實現與OP相同的功能,但是這讓我意識到我可以不添加多個控件實例,只需在模式窗口中顯示新控件,並在她的模式中「保存」,提交到數據存儲區並然後很容易地加載到頁面上。一千謝謝你。我已經花了3天時間,今天晚上都試圖弄清楚這一點。 – 2014-07-23 14:30:36

0

嘗試增加,

if(!Page.IsPostback) 
    --- your code that adds different controls. 
+0

我在!IsPostBack中包裹了Page_Init中的所有內容if。這樣做會加載鏈接按鈕和頁面的初始狀態,但是當我點擊其中一個鏈接按鈕時,它們全部消失並且頁面上沒有任何內容。 – 2010-11-18 15:36:27

1

我相信,你將需要在重新每個控制每回發。

我知道Repeater控件在數據綁定時存儲足夠的關於它的子項的信息以重新創建它們......您可能可以使用它來節省一些工作。

+0

您需要在每次回傳中重新創建它們是正確的。某處你需要儲存你已有的數量。也許在Viewstate或其他東西。 – Remy 2010-11-18 19:21:04

11
void lbAddFilter_Click(object sender, EventArgs e) 
{ 
    TextBox tb = new TextBox(); 
    tb.ID = "tb" + DateTime.Now.ToBinary().ToString(); 
    pnlFilter.Controls.Add(tb); 
} 

這不會起作用 - 這是一個生命週期問題,正如您在問題中推斷的那樣。有很多方法可以解決這個問題,但瓦納的建議是最靈活的。

這裏發生的事情是,您在事件處理程序中調用Controls.Add並將控件添加到控件列表中,並且在下一個請求中(無論是部分回發,完整回發還是新頁面命中),那個控制已經消失了,因爲你沒有堅持到任何地方。

這裏發生的事情在你的頁面事件生命週期現在:

  1. 頁面調用的OnInit,並增加你的LinkBut​​ton的
  2. 用戶點擊LinkBut​​ton的
  3. 頁面調用的OnInit開始回發請求。LinkBut​​ton的是重新
  4. 事件處理程序被調用,動態創建文本框的,並把它添加到控件集合
  5. 用戶點擊LinkBut​​ton的再次
  6. 頁面調用的OnInit再次添加LinkBut​​ton的。此時pnlFilter.Controls集合是空的,除了您在標記中靜態聲明的任何元素。
  7. 調用事件處理函數,並將新的TextBox添加到控件列表中。

我不知道,這是最好的做法,但我已經與此類似(注意,我沒有測試此代碼 - 這可能需要調整)一個模式的成功:

protected override void OnInit(EventArgs e) 
{ 
    base.OnInit(e); 

    LinkButton lb = new LinkButton(); 
    lb.ID = "lbAddFilter"; 
    pnlFilter.Controls.Add(lb); 
    lb.Text = "Add Filter"; 
    lb.Click += new EventHandler(lbAddFilter_Click); 

    // regenerate dynamically created controls 
    foreach (var control in PersistedControls) 
    { 
     pnlFilter.Controls.Add(GenerateControl(control)); 
    } 
} 

private IList<Control> _persistedControls; 
private const string PersistedControlsSessionKey = "thispage_persistedcontrols"; 
private IList<Control> PersistedControls 
{ 
    if (_persistedControls == null) 
    { 
     if (Session[PersistedControlsSessionKey] == null) 
      Session[PersistedControlsSessionKey] = new List<Control>(); 
     _persistedControls = Session[PersistedControlsSessionKey] as IList<Control>; 
    } 
    return _persistedControls; 
}  

void lbAddFilter_Click(object sender, EventArgs e) 
{ 
    TextBox tb = new TextBox(); 
    tb.ID = "tb" + DateTime.Now.ToBinary().ToString(); 
    PersistedControls.Add(tb); 
    pnlFilter.Controls.Add(tb); 
} 

請注意,我不確定是否將實際的控件對象添加到會話存儲 - 我相信存在控件ID會在回發時導致錯誤(也許控件不可序列化?)的問題。在我開發的解決方案中,我生成了一個新的TextBox/Label/ComboBox /等同於GenerateControl方法,並在PersistedControls集合中存儲了一個自定義容器類,該集合包含需要生成的UI控件的各種屬性它在每個頁面上初始化。