你的第一個假設是正確的。
對於第二個問題,它取決於它是否回發和/或您是否明確約束。如果不是回發並且綁定自動發生,那麼粗略地說,當DataSourceView在OnSelecting事件之前調用DataBind上的Select時,將檢索ControlParameter的值。爲GridView序列(和與此有關的任何給定的控制)如下:
Page.ProcessRequest
Page.PreRenderRecursiveInternal
...
GridView.EnsureChildControls
GridView.CreateChildControls
GridView.DataBind
GridView.PerformSelect
DataSourceView.Select //comes from either SQLDataSource or LinqDataSource
DataSourceView.ExecuteSelect
//for Linq:
LinqDataSourceView.GetParameterValues(WhereParameters)
//for SQL:
SqlDataSourceView.InitializeParameters(SelectParameters)
Parameters.GetValues
Parameters.UpdateValues //this is where values get retrieved using reflection
DataSourceView.OnSelecting //follows almost immediately
...get data...
DataSourceView.OnSelected
所以,對於在控制層次中的每個控制,該框架遞歸調用的DataBind,這隨後觸發的參數,OnSelecting檢索,數據檢索和OnSelected。
但是,如果它是回發,那麼這些參數將從頁面的OnLoadComplete上的視圖狀態再次按它們聲明的順序加載。
這是你在找什麼?
編輯
Q1 - 假設ControlParameter綁定到控制C.我會想象在回傳的財產C1 ControlProperty總是能夠得到的ViewState C.C1的價值,無論是C是什麼類型,即使C ViewState被禁用?!
這不完全是如何碰巧......在回傳(以及與此有關的初始請求),ControlParemeter的視圖狀態時,纔會評估,看它是否改變,從而OnParameterChanged事件可能會被解僱。 ControlParameter的實際值是根據它指向的控件進行評估的(通過反射)。在你的情況下,它會是「C.C1」。現在,當它讀取C.C1時,它的值很可能是從視圖狀態讀取的。但是,ControlParameter不會直接讀取C的視圖狀態。
Q2 - 但我可以問,爲什麼,如果第一次創建頁面,ControlParameter的值也不能從viewstate中獲取?最後,當lstCities從數據源檢索數據時,lstCities.SelectedValue是否設置了它的值?
就是這樣,在這個時候(第一次頁面加載時)lstCities沒有檢索到任何數據。屬性評估第一次發生在Page.OnLoadComplete上,但在任何DataBind之前(發生Page.PreRenderRecursiveInternal後不久)。
在原油的形式,試圖將其放置在頁面的生命週期:
...request...
PerformPreInit
InitRecursive //SqlDataSource subscribes to Page.LoadComplete
OnInitComplete
if PostBack
LoadAllState //the view state gets loaded
ProcessPostData
OnPreLoad
LoadRecursive
if PostBack
ProcessPostData
RaiseChangedEvents
RaisePostBackEvents //you handle your events
//notice that following sections assume that you did not do any data
//binding inside your events
OnLoadComplete //This is where parameters (SelectParemeters/WhereParemeters)
//get updated. At this point none of them are data bound yet.
//And if it the first time, there are no values
//as the ViewState is empty for them.
PreRenderRecursiveInternal //calls the DataBind (if you haven't already),
//then DataSourceView.Select; parameters evaluate their controls.
//The control C would be bound at this point.
PerformPreRenderComplete
SaveAllState
OnSaveStateComplete
RenderControl
第二個編輯
所以ControlParameter評估C.C1,從而獲取C.C1的C被綁定後的值?!的onLoadComplete和的DataBind(由PreRenderRecursiveInternal觸發):每當有人問,在這種情況下在兩個地方發生的(間接)
的ControlParameter檢索值。在OnLoadComplete上,C沒有綁定。在PreRenderRecursiveInternal上,在DataBind之後,C被綁定。這兩次ControlParameter被要求閱讀C.C1。也許以下會幫助...
下面是感興趣的類和方法。將它們放在頁面週期的角度,希望它會很清楚。
public class ControlParameter : Parameter
{
public string ControlID { get; set; } //stored in ViewState
public string PropertyName { get; set; } //stored in ViewState
protected override object Evaluate(HttpContext context, Control owner)
{
Control sourceControl = DataBoundControlHelper.FindControl(owner, this.ControlID);
//evaluate C.C1 using reflection
return DataBinder.Eval(sourceControl, this.PropertyName);
}
internal void UpdateValue(HttpContext context, Control owner)
{
//PostBack or not, read stored value (on initial load it is empty)
object storedValue = this.ViewState["ParameterValue"];
//Get the actual value for this parameter from C.C1
object actualValue = this.Evaluate(context, owner);
//Store received value
this.ViewState["ParameterValue"] = actualValue;
//Fire a change event if necessary
if ((actualValue == null && storedValue != null)
|| (actualValue != null && actualValue != storedValue))
this.OnParameterChanged();
}
}
public class SqlDataSource : DataSourceControl
{
//fired by OnLoadComplete
private void LoadCompleteEventHandler(object sender, EventArgs e)
{
//UpdateValues simply calls the UpdateValue for each parameter
this.SelectParameters.UpdateValues(this.Context, this);
this.FilterParameters.UpdateValues(this.Context, this);
}
}
public class SqlDataSourceView : DataSourceView, IStateManager
{
private SqlDataSource _owner;
//this method gets called by DataBind (including on PreRenderRecursiveInternal)
protected internal override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
{
DbConnection connection = this._owner.CreateConnection(this._owner.ConnectionString);
DbCommand command = this._owner.CreateCommand(this.SelectCommand, connection);
//This is where ControlParameter will read C.C1 values again.
//Except this time, C.C1 will be already populated by its own DataBind
this.InitializeParameters(command, this.SelectParameters, null);
command.CommandType = GetCommandType(this.SelectCommandType);
SqlDataSourceSelectingEventArgs e = new SqlDataSourceSelectingEventArgs(command, arguments);
this.OnSelecting(e);
if (e.Cancel)
return null;
//...get data from DB
this.OnSelected(new SqlDataSourceStatusEventArgs(command, affectedRows, null));
//return data (IEnumerable or DataView)
}
private void InitializeParameters(DbCommand command, ParameterCollection parameters, IDictionary exclusionList)
{
//build exlusions list
//...
//Retrieve parameter values (i.e. from C.C1 for the ControlParameter)
IOrderedDictionary values = parameters.GetValues(this._context, this._owner);
//build command's Parameters collection using commandParameters and retrieved values
//...
}
}
A)所以ControlParameter檢查其是否ViewState的變化......
參考UpdateValue方法上面看到它如何使用ViewState中。
B)我認爲ControlParameter檢查其是否視圖狀態只更改,以便它可以觸發事件OnParameterChanged。但爲什麼處理這個事件如此重要?
我不知道這很重要。我想,就像任何其他事件一樣,它允許您跟蹤參數屬性的更改並根據您的需要採取相應行動。它在許多地方被炒魷魚,但我沒有看到任何人訂閱它。所以...
通過屬性評估你的意思是ControlParameter檢查自己的ViewState?因此,你不是說ControlParameter評估C.C1(我假設C已被綁定後發生)
這意味着ControlParameter.UpdateValue被調用,這對於陳述的理由檢查ViewState中,然後調用ControlParameter.Evalue ,然後找到一個控件並使用反射(Eval)檢索數據。往上看。
第三編輯
我相信,通過更新你的意思是UpdateValue。
因此,如果更新()被調用時,數據綁定發生,那麼這是什麼意思是,當在下次回發更新()被調用的onLoadComplete,C.C1和ControlParameter已經將有相同的價值觀...
沒有必要。您忘記了視圖狀態在LoadAllState上加載,並且在它和OnLoadComplete之間還有六個步驟(請參閱上面的頁面生命週期)。其中每個可能會修改源代碼管理的(C.C1)值。
假設你有C.C1 =「x」並做了回帖。現在,所有控件的視圖狀態都被加載(LoadAllState)。如果C.C1將它的值存儲在視圖狀態中,它將加載「x」。在Page_Load(LoadRecursive)上,您決定設置C.C1 =「y」。這裏C.C1可能決定將「y」存儲在它的視圖狀態或不存在 - 這是無關緊要的。接下來的其他事件。接下來是OnLoadComplete。由於SqlDataSource的贊同這種情況下,它會評估所有相關的參數(LoadCompleteEventHandler),而且由於你沒有改變C.C1但ControlParameter的視圖狀態沒了,
if ((actualValue == null && storedValue != null)
|| (actualValue != null && actualValue != storedValue))
this.OnParameterChanged();
將返回true和OnParameterChanged將被解僱。順便說一下,這個活動至少有十個地方被觸發。它在數據綁定和屬性檢索過程中不起重要作用(如果有的話)。
我已經更新了我的答案。簡而言之,Q1 - ControlParameter只讀取自己的狀態,並且只確定它是否改變; Q2 - ControlParameter總是評估C.C1,而不是視圖狀態,此時C.C1爲空(或默認),因爲在視圖狀態中沒有任何內容,並且沒有DataBind。 – Ruslan 2009-04-08 21:36:26
提供更多信息,附帶一些代碼。 – Ruslan 2009-04-09 15:32:09