2008-09-05 99 views
7

我有一個相當複雜的頁面,它動態構建了一箇中繼器內的用戶控件。在初始化ViewState之前,必須在初始頁事件期間綁定此中繼器,否則動態創建的用戶控件將不會保留其狀態。當您無法使用ViewState時,您會做什麼?

這就產生了一個有趣的捕捉-22,因爲我結合中繼器需要的對象上初始頁面加載被創建,然後在持續存儲器中,直到用戶選擇離開或保存。

因爲我不能用ViewState來存儲這些對象,但有它初始化過程中可用,我已經被迫將其存儲在會話。

這也有問題,因爲我必須明確地空以模擬如何ViewState工作在非回發會話值。

在這種情況下,必須有更好的狀態管理方法。有任何想法嗎?

編輯:關於使用LoadViewState的一些很好的建議,但我仍然有狀態不恢復時,我這樣做。

這裏是有些如果頁面結構

頁 - >用戶控件 - >中繼器 - >用戶控件的氮量動態地創建。

我把覆蓋的LoadViewState放在父UserControl中,因爲它被設計成完全封裝並且獨立於它所在的頁面。我想知道這是否是問題所在。

回答

1

這也有問題,因爲我必須在非回發期間顯式地將會話值清空以模擬ViewState的工作方式。

爲什麼你顯式空值(除內存管理等)?是不是選擇檢查Page.IsPostback,並且對Session變量做些什麼或不做?

1

我總是在LoadViewState事件中重新創建我的動態控件。您可以在viewstate中存儲需要創建的控件的數量,然後使用LoadViewState事件中的LoadControl方法動態創建其中的許多控件。在這種情況下,您可以訪問ViewState,但尚未恢復到頁面上的控件。

0

@DancesWithBamboo:

如果我動態綁定的控件存在,ASP.NET會自動處理它們的狀態?在Page_Load中做這件事的問題是,viewstate已經被加載,並且不會在中繼器中添加動態控件。我認爲它會在LoadViewState中做同樣的事情?

+0

您使用的是數據綁定嗎?我從來沒有在asp.net中使用它,它可能會改變遊戲領域。但是,LoadViewState是應該用於在回退時間恢復動態控件的事件。 PageLoad在生命週期中肯定太晚了。 – DancesWithBamboo 2008-09-09 15:06:26

0

1)可能有辦法讓它工作......你只需要確保在正確的時刻將你的控件添加到樹中。很快,你不會得到ViewState。太晚了,你沒有得到ViewState。

2)如果你不能弄清楚,也許你可以關閉視圖狀態的孔頁面,然後只在查詢字符串的狀態變化依賴?任何以前回發的鏈接都將是另一個URL的鏈接(或回發重定向)。

這真的可以減少頁面的權重,並使其更容易避免的ViewState的問題。

0

@Jonathan:

是,運行時將只要你創建它們的權數填充控件的視圖狀態。控件的視圖狀態將在此事件之後生成。

0

是的,只要您創建正確的數量,運行時就會填充控件的視圖狀態。控件的視圖狀態將在此事件之後生成。

按照什麼順序被稱爲LoadViewState?我添加了一個重寫的方法簽名,它似乎沒有進入它。

0
protected override void LoadViewState(object savedState) 
{ 
    // Put your code here before base is called 
    base.LoadViewState(savedState); 
} 

這是你的意思嗎?或者你的意思是控制處理的順序是什麼?我認爲這個答案是準隨機的。

而且,你爲什麼不能加載你的Page_Load之前綁定的對象?如果必須的話,在頁面生命週期的任何時候調用業務層都可以,除了預渲染之外的任何事情。

0

我必須明確地空在非回發會議 值以 模擬如何ViewState的作品。

我還在雲裏霧裏,爲什麼你不能存儲任何對象(或多個)要針對在會話綁定。如果您可以在會話中存儲該對象,則以下內容應該可以工作:

  1. 在第一次加載時,在OnPreInit期間將最高用戶控件綁定到對象。將對象存儲在會話中。 Viewstate將自動存儲這些控件。如果您必須在Page_Load上第一次綁定控件,那麼確定,但如果您執行下一步,則最終會有兩個調用綁定的事件。
  2. 在回發,重新綁定在對你存儲在會話對象中的OnPreInit方法的頂部的用戶的用戶控制。應該在視圖狀態加載之前重新創建所有的控件。然後當viewstate恢復時,這些值將被設置爲viewstate中的任何值。唯一需要注意的是,當你在回發時重新綁定時,你必須100%確保再次創建相同數量的控件。關鍵要使用中繼器,GridView的等等......與他們的內部動態控件是他們是在每次反彈回發加載視圖狀態之前。 OnPreInit通常是最好的地方。在框架中沒有任何技術限制,這意味着您必須在第一次加載時在Page_Load中完成所有工作。

這應該有效。但是,如果由於某種原因無法使用會話,則必須採取稍微不同的方法,例如在綁定控件後將所綁定的任何內容存儲在數據庫中,然後將其從數據庫中拉出並重新綁定再次在每個回發。

我是否缺少關於您的情況的一些明顯細節?我知道,如果沒有發佈代碼,解釋情況的微妙之處可能會非常棘手。

編輯:我在此解決方案中將OnInit的所有引用更改爲OnPreInit。我忘了MS在ASP.NET 2.0中引入了這個新事件。根據他們的page lifecycle documentation,OnPreInit是應該創建/重新創建動態控件的地方。

0

創建動態控件時......我只在初始加載時填充它們。 Afterwords我在頁面加載事件中重新創建回發控件,viewstate似乎處理重新填充的值而沒有問題。

4

頁面上的LoadViewState方法絕對是答案。這裏的總體思路:

protected override void LoadViewState(object savedState) { 
    var savedStateArray = (object[])savedState; 

    // Get repeaterData from view state before the normal view state restoration occurs. 
    repeaterData = savedStateArray[ 0 ]; 

    // Bind your repeater control to repeaterData here. 

    // Instruct ASP.NET to perform the normal restoration of view state. 
    // This will restore state to your dynamically created controls. 
    base.LoadViewState(savedStateArray[ 1 ]); 
} 

SaveViewState需要創建我們在上面使用savedState陣列:

protected override object SaveViewState() { 
    var stateToSave = new List<object> { repeaterData, base.SaveViewState() }; 
    return stateToSave.ToArray(); 
} 

不要忘了也結合在初始化中繼器或使用這樣的代碼加載:

if(!IsPostBack) { 
    // Bind your repeater here. 
} 
相關問題