Ihre erste Annahme richtig ist.
Zu Ihrer zweiten Frage kommt es darauf an, ob es sich um einen Postback handelt oder nicht und/oder ob Sie explizit verbindlich sind. Wenn das Postback und die Bindung nicht automatisch erfolgen, wird grob gesagt der Wert des ControlParameters abgerufen, wenn DataSourceView Select on DataBind aufruft, direkt vor OnSelecting event. Die Sequenz für den Grid (und jede gegebene Steuer was das betrifft) ist wie folgt:
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
So wird für jede Steuerung in einer Steuerhierarchie, der Rahmen rekursiv aufruft DataBind, die dann den Abruf von Parametern auslöst, OnSelecting, Datenabruf und OnSelected.
Wenn es sich jedoch um ein Postback handelt, werden diese Parameter erneut aus einem Viewstate auf der OnLoadComplete der Seite geladen, wiederum in der Reihenfolge, in der sie deklariert sind.
Ist das wonach Sie gesucht haben?
bearbeiten
Q1 - Nehmen wir an, Control auf Eigentum C1 eines Steuer C gebunden ist, ich, dass auf Postbacks ControlProperty immer C.C1 Wert von Viewstate, der Lage wäre, sich vorstellen würde, egal zu bekommen von welchem Typ C ist, und selbst wenn C ViewState deaktiviert hat ?!
Das ist nicht ganz, wie es kommt ... Auf Post zurück (und bei dem ersten Anfrage für diese Angelegenheit), wird ControlParemeter Sicht Zustand nur dann ausgewertet, um zu sehen, ob es so geändert, dass das OnParameterChanged Ereignis ausgelöst werden könnte. Der tatsächliche Wert des ControlParameters wird mit dem Steuerelement verglichen, auf das er zeigt (über die Reflektion). In Ihrem Fall wäre es "C.C1". Jetzt, wenn es C.C1 liest, wird sein Wert wahrscheinlich aus einem Ansichtszustand gelesen. Aber zu keinem Zeitpunkt liest das ControlParameter den C-View-Zustand direkt.
Q2 - Aber darf ich fragen warum, wenn eine Seite zum ersten Mal erstellt wird, kann auch kein Wert für ControlParameter aus Viewstate abgerufen werden? Nach dem Moment, in dem lstCities Daten aus der Datenquelle abruft, wird lstCities.SelectedValue gesetzt?
Das ist die Sache, an diesem Punkt (das erste Mal, wenn die Seite geladen wird) hat die lstCities noch keine Daten abgerufen. Das erste Mal, wenn eine Eigenschaftsauswertung stattfindet, befindet sich auf Page.OnLoadComplete, aber vor jedem DataBind (was kurz darauf passiert, wenn Page.PreRenderRecursiveInternal ausgelöst wird).
In der rohen Form, versucht, es in einem Lebenszyklus einer Seite zu platzieren:
...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
Zweite bearbeiten
So Control C.C1 auswertet und somit ruft C.C1 der Wert nach C wurde gebunden ?!
Die Control ruft Werte, wenn sie gefragt wird, was in diesem Szenario geschieht (indirekt) an zwei Stellen: OnLoadComplete und DataBind (ausgelöst durch PreRenderRecursiveInternal). Bei OnLoadComplete ist das C nicht gebunden. Auf PreRenderRecursiveInternal, nach DataBind, ist das C gebunden. Beide Male wird ControlParameter aufgefordert, C.C1 zu lesen. Vielleicht hilft das folgende ...
Hier sind Klassen und Methoden von Interesse auf den Punkt gebracht. Stellen Sie sie in die Perspektive des Seitenzyklus und hoffentlich wird es klar sein.
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) So Controlparameter prüft, ob seine Viewstate geändert ...
Siehe die Updatemethode oben zu sehen, wie es verwendet Viewstate.
B) Ich gehe davon aus Control prüft, ob seine Viewstate nur geändert, so dass es OnParameterChanged Ereignis auslösen kann. Aber warum ist der Umgang mit dieser Veranstaltung so wichtig?
Ich weiß nicht, dass es wichtig ist. Ich nehme an, dass Sie wie jedes andere Ereignis Änderungen der Parametereigenschaften verfolgen und entsprechend Ihren Anforderungen handeln können. Es wird an vielen Orten gefeuert, aber ich sehe nicht, wo jemand es abonniert. So ...
Bei der Bewertung der Eigenschaften meinen Sie, dass ControlParameter seinen eigenen ViewState überprüft? So meinen Sie nicht Control Auswertung C.C1 (was ich davon ausgehen, passiert nach C gebunden wurde)
Es bedeutet, dass die ControlParameter.UpdateValue, die genannten Gründen Viewstate prüft aufgerufen wird, dann ruft ControlParameter.Evalue , die dann ein Steuerelement findet und Daten mithilfe der Reflektion (Eval) abruft. Siehe oben.
Dritte bearbeiten
Ich nehme an, dass durch Aktualisieren Sie Update bedeuten.
Also, wenn Update() aufgerufen wird, wenn die Datenbindung stattfindet, dann ist das, was bedeutet, dass, wenn auf dem nächsten Postback Update() in OnLoadComplete, C.C1 und Control bereits gleiche Werte genannt haben wird ...
Nicht erforderlich. Sie vergessen, dass der Ansichtszustand auf LoadAllState geladen ist und zwischen diesem und dem OnLoadComplete noch sechs weitere Schritte (siehe oben auf der Seite Lebenszyklus). Jeder dieser Parameter kann den Wert des Quellsteuerelements (C.C1) ändern.
Angenommen, Sie haben C.C1 = "x" und haben einen Beitrag zurück geschrieben. Jetzt wird der Ansichtszustand für alle Steuerelemente geladen (LoadAllState). Wenn C.C1 seinen Wert im Ansichtszustand speichert, wird "x" geladen. Bei Page_Load (LoadRecursive) entscheiden Sie, C.C1 = "y" festzulegen. Hier kann C.C1 entscheiden, "y" in seinem Ansichtszustand zu speichern oder nicht - es ist irrelevant. Dann folgen andere Ereignisse. Als nächstes kommt OnLoadComplete. Da SqlDataSource auf dieses Ereignis abonniert hat, werden alle zugehörigen Parameter (LoadCompleteEventHandler) und bewerten, da Sie ändern tat C.C1 aber Control Sicht Staat nicht, die
if ((actualValue == null && storedValue != null)
|| (actualValue != null && actualValue != storedValue))
this.OnParameterChanged();
wahr zurück und OnParameterChanged wird gefeuert werden. Übrigens gibt es mindestens zehn andere Orte, an denen dieses Ereignis ausgelöst wird. Es spielt keine große Rolle (wenn überhaupt) in Datenbindung und Property Retrieval-Prozess.
Ich habe meine Antwort aktualisiert. Kurz gesagt liest Q1 - ControlParameter nur seinen eigenen Status und nur um festzustellen, ob es sich geändert hat; Q2 - ControlParameter wertet immer C aus.C1, nicht der Ansichtszustand, und an diesem Punkt ist C.C1 leer (oder Standard), da sich im Ansichtszustand nichts befindet und noch kein DataBind vorhanden war. – Ruslan
Weitere Informationen zur Verfügung gestellt, mit etwas Code. – Ruslan