あなたの最初の仮定は正しいです。
2 番目の質問に対しては、それがポストバックかどうか、および/または明示的にバインドしているかどうかによって異なります。ポスト バックではなく、バインドが自動的に行われる場合、大まかに言えば、DataSourceView が DataBind で Select を呼び出すときに、OnSelecting イベントの直前に ControlParameter の値が取得されます。グリッドビュー (およびそのための任意のコントロール) のシーケンスは次のとおりです。
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 にバインドされていると仮定します。ポストバックでは、C の型に関係なく、また C の ViewState が無効になっている場合でも、ControlProperty は常に ViewState から C.C1 の値を取得できると思います。 ?!
それが完全に起こるわけではありません...ポストバック時(およびその問題の最初のリクエスト時)、ControlParemeterのビューステートは、OnParameterChangedイベントが発生するように変更されたかどうかを確認するためだけに評価されます. ControlParameter の実際の値は、それが指すコントロールに対して (リフレクションを介して) 評価されます。あなたの場合、それは「C.C1」になります。現在、C.C1 を読み取る場合、その値はおそらくビューステートから読み取られます。しかし、ControlParameter が C のビュー ステートを直接読み取ることは決してありません。
Q2 - ページが初めて作成された場合、ControlParameter の値もビューステートから取得できないのはなぜですか? 結局、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
2 回目の編集
ControlParameter は C.C1 を評価し、C がバインドされた後に C.C1 の値を取得しますか?!
ControlParameter は、要求されるたびに値を取得します。このシナリオでは、OnLoadComplete と DataBind (PreRenderRecursiveInternal によってトリガーされる) の 2 つの場所で (間接的に) 発生します。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 が変更されたかどうかを確認します...
ViewState の使用方法については、上記の UpdateValue メソッドを参照してください。
B) ControlParameter は、OnParameterChanged イベントを発生させるためだけに Viewstate が変更されたかどうかをチェックすると仮定します。しかし、なぜそのイベントの処理がそれほど重要なのでしょうか?
私はそれが重要であることを知りません。他のイベントと同様に、パラメーターのプロパティの変更を追跡し、ニーズに応じて行動できると思います。それは多くの場所で解雇されますが、誰もそれを購読しているとは思いません。そう...
プロパティの評価とは、ControlParameter が独自の ViewState をチェックしていることを意味しますか? したがって、C.C1 を評価する ControlParameter を意味するわけではありません (C がバインドされた後に発生すると想定しています)。
これは、ControlParameter.UpdateValue が呼び出され、ViewState が指定された理由でチェックされ、次に ControlParameter.Evalue が呼び出され、コントロールが検出され、リフレクション (Eval) を使用してデータが取得されることを意味します。上記を参照。
3 回目の編集
Updateとは、UpdateValueを意味すると思います。
したがって、データバインディングが行われるときに Update() が呼び出されると、次のポストバックで OnLoadComplete で UpDate() が呼び出されたときに、C.C1 と ControlParameter はすでに同じ値を持っていることを意味します...
必要はありません。ビュー ステートが LoadAllState に読み込まれ、それと OnLoadComplete の間にさらに 6 つのステップがあることを忘れています (上記のページ ライフサイクルを参照)。それらのそれぞれは、ソース管理の (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 が発生します。ちなみに、このイベントがトリガーされる場所は他に少なくとも 10 か所あります。データバインディングとプロパティ取得プロセスでは、(もしあれば) 大きな役割を果たしません。