2009-04-07 27 views
2


如果控件始終是綁定到數據源控件的聲明順序排列,然後

A)以下問題是基於這樣的假設控件始終是綁定在預定數據源控件它們聲明?所以,在我們的例子SqlDataSource1將連接到數據源之前SqlDataSource2從而lstCities將值之前GridView1填充,並宣稱原因是在於lstcitiesGridView1?!



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" …> 
    </asp:GridView> 


感謝名單

編輯:

如果是回發,但隨後這些參數會得到從裝在頁面的OnLoadComplete上的viewstate,再次按照它們聲明的順序。

Q1 - 假設ControlParameter綁定到控制C.我會想象在回傳的財產C1 ControlProperty總是能夠從ViewState中,沒有C是什麼類型的事情得到C.C1的價值,即使C ViewState禁用?!

Q2 - 但是我可以問爲什麼,如果是第一次創建了一個頁面,不能爲ControlParameter值也可以從視圖狀態檢索?最後,當lstCities從數據源檢索數據時,lstCities.SelectedValue是否設置了它的值?



感謝名單隊友


第二個編輯:

我不及早回信,但是我不知道你已經回答。當我做到了,我花了整整20分鐘試圖讓我的3個braincells才能正常工作,但我不知道如果我很成功


A)所以ControlParameter評估C.C1和從而在C被綁定後檢索C.C1的值?!


Q1 - ControlParameter只讀取自己的狀態,只有以確定它是否改變了

A)所以ControlParameter檢查它的ViewState是否改變(在之前,爲了激發OnParameterChanged事件)綁定發生 - >因此它在Page.OnLoadComplete期間檢查它的ViewState。 但是ControlParameter如何知道它的ViewState已經改變了(它會在第一次回發中知道)?最後,從第一次創建頁面開始,ControlParameter的ViewState將始終被標記爲髒,那麼從一次回發到另一次回送,ControlParameter將如何知道其值在回發之間是否發生了變化?

B)我假設ControlParameter檢查它的Viewstate是否只改變了,以便它能觸發OnParameterChanged事件。但爲什麼處理這個事件如此重要?


第一次物業評估情況是在Page.OnLoadComplete

通過你的意思是ControlParameter檢查自己的ViewState屬性的評價?因此,你不是說ControlParameter評估C.C1(我假設C已被綁定後發生)


我真的很感謝你的幫助


第三編輯:

我真的很抱歉再次把你的時間。我會盡我所能,使這個我最後編輯。


更新()都在的onLoadComplete和當數據綁定發生被調用。內部更新()也執行了下面的句子:

this.ViewState["ParameterValue"] = actualValue; 

因此,如果更新()被調用時,數據綁定發生,那麼這意味着什麼是 爲:當在下一回發更新()被調用的onLoadComplete, C.C1和ControlParameter已經將有相同的價值觀,從而

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

將始終返回false(更新時()被調用的onLoadComplete),如果是這樣OnParameterChanged事件永遠不會被解僱?1,我失敗看到需要在OnLoadComplete中調用Update()!


非常感激

+0

我已經更新了我的答案。簡而言之,Q1 - ControlParameter只讀取自己的狀態,並且只確定它是否改變; Q2 - ControlParameter總是評估C.C1,而不是視圖狀態,此時C.C1爲空(或默認),因爲在視圖狀態中沒有任何內容,並且沒有DataBind。 – Ruslan 2009-04-08 21:36:26

+0

提供更多信息,附帶一些代碼。 – Ruslan 2009-04-09 15:32:09

回答

2

你的第一個假設是正確的。

對於第二個問題,它取決於它是否回發和/或您是否明確約束。如果不是回發並且綁定自動發生,那麼粗略地說,當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將被解僱。順便說一下,這個活動至少有十個地方被觸發。它在數據綁定和屬性檢索過程中不起重要作用(如果有的話)。