簡體   English   中英

asp.net在回發后動態添加用戶控件保存值

[英]asp.net dynamically added user control saving values after postback

這是我的問題。 我有一個usercontrol,我希望允許用戶使用按鈕單擊添加任意數量的實例(每次單擊一個按鈕,我想將另一個用戶控件實例添加到Panel)。 它第一次工作正常,但每個額外的回發刪除所有添加的控件。 我跟蹤用戶添加的用戶控件的數量沒有問題,但我如何確保它們保持在回發之前的狀態? 我已經閱讀了一些關於使用SaveViewState和LoadViewState的人的帖子,但我找不到任何例子。

我最大的問題是確保每個用戶控件的所有文本框和下拉列表在每個回發后都保持填充相同的文本/選定值/數據

提前謝謝,本

由於您是以編程方式向頁面添加控件,因此您需要在每次回發時重新創建它們。

此外,您必須在頁面的PreInitInit事件上重新創建以編程方式添加的控件。 這適用於正確的視圖狀態恢復事件管理。

如果你不這樣做,控制將在回發時消失,他們將不會處理任何事件。

編輯

雖然建議在PreInitInit上添加動態控件,但它是真的(如Dustin Hodges所說),如果你在page_load上添加它們可能會有效。 我會說你應該避免它,除非你別無選擇。

您可以在Page_Load事件處理程序中加載控件並正確維護視圖狀態。
這完全取決於您是否以編程方式設置動態加載控件的任何屬性,如果是,則相對於Controls.Add(dynamicControl)行執行此操作。
對此的深入討論有點超出了本文的范圍,但它可能起作用的原因是因為Controls屬性的Add()方法以遞歸方式將父視圖狀態加載到其子節點中,即使已經過了加載視圖狀態階段。

來源MSDN

如果要跟蹤用戶添加的控件數量,則需要重新創建用戶之前添加的控件,最好是在Page_Init或Page_Load中。 將這樣的內容添加到該處理程序:

for(int i=0; i<NumberOfControlsUserHasAdded; i++)
{
    //todo:  change this to the appropriate user control
    TextBox tb = new TextBox();
    tb.ID = "tb" + i.ToString();
    //todo:  add to appropriate control collection
    this.Controls.Add(tb);
}

如果你這樣做,應該保持控件的狀態,因為當你將tb控件添加到控件集合時,它會捕獲事件並自動恢復其viewstate。

您不必在會話中跟蹤其狀態,因為在大多數情況下,它將存儲在視圖狀態中

我有一個噩夢,試圖在一個舊項目上解決這個問題。 在中間階段,我發現我對Web開發的了解遠遠少於我的想法(閱讀這個網站是一個很好的方式來謙卑自己每天 - 如果不是每小時 - 基礎上)。 在那個項目中,Page.IsPostBack對我來說完全沒用,因為我已經動態地實例化了控件。

話雖這么說,我建議的最好的事情是考慮使用Session變量。 如果你有一個類(或類的集合)代表你從頁面捕獲的數據,那么也許最容易在該類/集合中存儲值以提高代碼可讀性,然后將其寫入會話。

查看您的PageLoad並在清除面板的行之前添加if(!this.IsPostBack)

這當然只是一個猜測,但我已經看到很多問題,問題與此有關

我認為可能發生的事情是當你點擊按鈕添加, Page_Load fires會為你創建一個全新的頁面。 然后,按鈕單擊方法添加控件,頁面完成渲染。 當您第二次單擊它時, Page_Load會創建您的頁面,再次按鈕單擊方法會創建一個控件並將其添加到頁面中。 不幸的是,你之前添加的那個不再存在。

如果您將控件添加到Repeater會怎樣? Repeater的視圖狀態可以跟蹤您添加的每個控件,以便在回發后,它不會被吹走。

如果您有大量用戶,這是一個丑陋的解決方案,但您可以將用戶控件自己粘貼到會話中。 我使用頁腳控件執行此操作,因為每次頁面更改以重新創建頁腳時我都不想訪問數據庫。

如果您擁有大量用戶並且他們使用此功能,則此解決方案可以在服務器上獲得真正的任務。 至少我認為它會......

但是你可以在page_load上重新填充其中包含usercontrols的占位符。 我可以很快提出一個例子。

我做的例子:

if (Session["footer"] == null)
{
 Session["footer"] = new Footer(LinksRules.BuildFooterLinks((int)WebSiteSections.Main));// where Footer is my control
}
footerPH.Controls.Add((Footer)Session["footer"]);

像單身模式一樣......

所以我看到它可以在任何會導致回發的事情上做到這一點

Session [“DynamicControls”] = PlaceHolder.Controls;

在頁面加載方法中,您可以:

foreach(var control in (List<Controls>)Session["DynamicControls"])
{
  yourPlaceHolder.Controls.Add(control);
}

如果會話對象為null,只需添加一個就像他們從未去過那里一樣。

我相信這會像你想要的那樣依賴於控件內部的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM