3


A) 以下の質問は、コントロールが常に宣言された順序でデータ ソース コントロールにバインドされるという仮定に基づいていますか? したがって、この例では、 SqlDataSource1 は SqlDataSource2 の前にデータ ソースに接続するため、lstCitiesにはGridView1の前に値が入力されます。その理由は、lstcitiesがGridView1の前に宣言されたからです。



B) その場合、ControlParameterがDropDownListから値を取得するのはいつですか? SqlDataSource1_Selected() イベント ハンドラーの後、SqlDataSource2_Selecting()イベントハンドラーの前だと思いますが、正確にはいつですか?

.aspx ページ:

    <asp:SqlDataSource ID="SqlDataSource1" ... >
    </asp:SqlDataSource>

    <asp:DropDownList ID="lstCities" DataSourceID="SqlDataSource1"
         DataTextField="City" runat="server"></asp:DropDownList>

    <asp:SqlDataSource ID="SqlDataSource2" ... >
        <SelectParameters>
            <asp:ControlParameter ControlID="lstCities" Name="City"
                 PropertyName="SelectedValue" />
        </SelectParameters>
    </asp:SqlDataSource>

    <asp:GridView DataSourceID="SqlDataSource2" runat="server" …&gt;
    </asp:GridView>


ありがとう

編集:

ただし、ポストバックの場合、これらのパラメーターは、宣言されている順序で、ページの OnLoadComplete のビューステートから再度読み込まれます。

Q1 - ControlParameter がコントロール C のプロパティ C1 にバインドされていると仮定します。ポストバックでは、C の型に関係なく、また C の ViewState が無効になっている場合でも、ControlProperty は常に ViewState から C.C1 の値を取得できると思います。 ?!

Q2 - しかし、ページが初めて作成された場合、ControlParameter の値もビューステートから取得できないのはなぜですか? 結局、lstCities がデータ ソースからデータを取得した瞬間、lstCities.SelectedValue には値が設定されているのでしょうか。



ありがとう


2番目の編集:

返信が遅れて申し訳ありませんが、返信があったことに気づきませんでした。そして、私が行ったとき、私は3つの脳細胞を適切に機能させるために20分を費やしましたが、完全に成功したかどうかはわかりません


A) ControlParameter は C.C1 を評価し、C がバインドされた後に C.C1 の値を取得しますか?!


Q1 - ControlParameter は自身の状態のみを読み取り、変更されたかどうかを判断するためだけに使用します

A) したがって、ControlParameter は、バインディングが行われる前に (OnParameterChanged イベントを発生させるために) ViewState が変更されたかどうかをチェックします --> したがって、Page.OnLoadComplete 中に ViewState をチェックします。しかし、ControlParameter は ViewState が変更されたことをどのように認識しますか (最初のポストバックで認識されます)。結局のところ、ページが最初に作成されたときから、ControlParameter の ViewState は常にダーティとしてマークされるため、あるポストバックから別のポストバックまで、ControlParameter はその値がポストバック間で変更されたかどうかをどのように知るのでしょうか?

B) ControlParameter は、OnParameterChanged イベントを発生させるためだけに Viewstate が変更されたかどうかをチェックすると仮定します。しかし、なぜそのイベントの処理がそれほど重要なのでしょうか?


プロパティの評価が初めて発生するのは、Page.OnLoadComplete です。

プロパティの評価とは、ControlParameter が独自の ViewState をチェックしていることを意味しますか? したがって、C.C1 を評価する ControlParameter を意味するわけではありません (C がバインドされた後に発生すると想定しています)。


私は本当にあなたの助けに感謝します


3番目の編集:

またお時間を頂戴してしまい、誠に申し訳ございません。これが最後の編集となるよう最善を尽くします。


Update() は、OnLoadComplete とデータ バインディングの両方で呼び出されます。Update() 内では、次の文も実行されます。

this.ViewState["ParameterValue"] = actualValue;

したがって、データバインディングが行われるときに Update() が呼び出されると、次のポストバックで OnLoadComplete で UpDate() が呼び出されたときに、C.C1 と ControlParameter はすでに同じ値を持っていることを意味します。

             if ((actualValue == null && storedValue != null)
             || (actualValue != null && actualValue != storedValue))

OnLoadComplete で Update() が呼び出された場合) は常に false を返すため、OnParameterChanged イベントは決して発生しませんか?1 その場合、OnLoadComplete で Update() を呼び出す必要があることがわかりません!


とても感謝しております

4

1 に答える 1

2

あなたの最初の仮定は正しいです。

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 か所あります。データバインディングとプロパティ取得プロセスでは、(もしあれば) 大きな役割を果たしません。

于 2009-04-08T18:34:53.800 に答える