2013-10-11 51 views
1

在過去,當開發動態加載多控件單頁類型的應用程序時,我有大量的視圖狀態問題。原因是控件必須添加到OnInit階段,而不是之後。由於我正在處理一個控件事件(例如,在dropdownlist中selectedIndexChanged),我在事件處理程序階段加載它們。我知道孩子控制頁面週期追趕,但我注意到,有時它不起作用。
從Request.Form中讀取值

我再一次負責開發這樣的應用程序。這次我決定採取不同的方法。對於那些根據它們的值加載動態控件的選擇控件,我將在OnInit階段檢查它們的回發響應值(來自Request.Form)並立即加載控件。我不會加載來自事件處理程序階段的任何動態控件,因爲這是在OnPreRender之前,並且爲時已晚。

總結:
什麼是在頁面週期的早期從Request.Form集合檢查控件的值(例如的OnInit),然後,執行操作的陷阱,而不是檢查,從實際控制值後在頁面週期?

回答

0

其中一個缺陷是,如果該控件未包含在<form>中,它將不存在。我建議繼續並在事件處理程序階段添加它們 - 因爲那時您知道要添加的內容 - 但存儲必要的信息以重建ViewStateSessionState中的那些控件。

通過這樣做,您將能夠在OnInit中重新創建它們,但不必處理現在正在走向的道路周圍的一些其他複雜性。

因此,假設您發現您需要構建控件。你會建立它:

var tb = new TextBox(); 
tb.ID = "myTextBox"; 
... 

,但你也想保存必要的狀態信息:

this.ViewState.StoreControl(typeof(TextBox), "myTextBox"); 

,然後就建立擴展方法:

public static void StoreControl(this StateBag vs, Type controlType, string name) 
{ 
    var dynamicControls = vs["DynamicControls"] as List<Tuple<Type, string>>; 
    if (dynamicControls == null) 
    { 
     dynamicControls = new List<Tuple<Type, string>>(); 
     vs["DynamicControls"] = dynamicControls; 
    } 

    var t = dynamicControls.FirstOrDefault(tp => tp.Item2 == name); 
    if (t == null) { dynamicControls.Add(Tuple.Create(controlType, name)); } 
} 

然後OnInit你可能會這樣做:

var dynamicControls = vs["DynamicControls"] as List<Tuple<Type, string>>; 
if (dynamicControls != null) 
{ 
    foreach (var tp in dynamicControls) 
    { 
     Control c = Activator.CreateInstance(tp.Item1) as Control; 
     c.ID = tp.Item2; 
     this.Controls.Add(c); 
    } 
} 

注意:此代碼寫在SO上。它沒有被編譯或調試。但你明白了。

+0

如何在asp.net服務器控件中不包含

? – BlueChameleon

+0

@BlueChameleon,它可以完成,我已經完成了。我不是說它會成爲主流 - 我只是說它可以完成。但是,請參閱我的編輯。 –

+0

老實說,我看到你在這裏做什麼,但你提到的原始陷阱在我們的系統中永遠不會發生,因爲如果我們開始在窗體外添加控件,我們不能使用Control.FindControl()來查找它們,這會破壞一切。再加上一堆標準的ASP.NET控件調用System.Web.UI.Page.VerifyRenderingInServerForm()來確保它們在表單中,否則它們會引發錯誤。 – BlueChameleon