2009-04-07 4 views
2


Wenn Kontrollen Datenquellensteuer in der Reihenfolge immer binded sind, werden sie dann erklärt

A) Frage unten auf der Annahme beruht, dass die Kontrollen an Datenquellensteuer in der Reihenfolge immer binded sind sie deklariert sind? In unserem Beispiel wird SqlDataSource1 zu Datenquelle verbinden vor SqlDataSource2 und damit lstCities wird mit den Werten vor GridView1 bevölkert werden, und Grund dafür ist, dass lstcities erklärt wurde vor GridView1?!



B) Wenn ja, dann, wenn genau funktioniert Control Wert von Dropdown abrufen? Ich nehme an, es ist nach SqlDataSource1_Selected() Event-Handler und vor SqlDataSource2_Selecting() Event-Handler, aber wann genau?

In ASPX-Seite:

<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> 


thanx

EDIT:

Wenn es ein Postback ist aber dann werden diese Parameter von einem geladen werden Viewstate auf der Seite OnLoadComplete erneut in der Reihenfolge, in der sie deklariert sind.

Q1 - Lassen Sie uns annehmen, Control auf Eigenschaft C1 eines Steuer C gebunden ich, dass auf Postbacks ControlProperty immer C ist C.C1 Wert von Viewstate, egal von der Lage wäre, zu bekommen, welche Art vorstellt und selbst wenn C ViewState deaktiviert hat ?!

Q2 - Aber wenn ich fragen darf, warum, wenn eine Seite zum ersten Mal erstellt wird, kann kein Wert für Control auch von Ansichtszustand abgerufen werden? Nach dem Moment, in dem lstCities Daten aus der Datenquelle abruft, wird lstCities.SelectedValue gesetzt?



thanx paaren


ZWEITE EDIT:

Ich entschuldige mich nicht früher antworten, aber ich wusste nicht, dass du geantwortet haben. Und wenn ich es tat, habe ich verbrachte gut 20 Minuten versucht meine 3 Gehirnzellen zu erhalten richtig zu arbeiten, aber ich bin nicht sicher, ob ich ganz

gelang


A) So Control wertet C.C1 und Auf diese Weise wird der Wert von C.C1 abgerufen, nachdem C gebunden wurde.


Q1 - Control liest nur seinen eigenen Zustand und nur, um zu bestimmen, ob es

A geändert) So Controlparameter prüft, ob seine Viewstate (in der Reihenfolge geändert OnParameterChanged Ereignis ausgelöst) vor Bindung findet statt -> so überprüft es seinen ViewState während Page.OnLoadComplete. Aber wie wird ControlParameter wissen, dass sein ViewState geändert wurde (es wird beim ersten Postback wissen)? Schließlich wird ControlParameters ViewState immer beim ersten Erstellen der Seite als "dreckig" gekennzeichnet. Wie also wird ControlParameter von einem Postback zum anderen wissen, ob sich sein Wert zwischen Postbacks geändert hat?

B) Ich nehme an, ControlParameter überprüft, ob sein Viewstate nur so geändert wurde, dass es OnParameterChanged-Ereignis auslösen kann. Aber warum ist der Umgang mit dieser Veranstaltung so wichtig?


Das erste Mal, wenn eine Immobilienbewertung ist auf Page.OnLoadComplete Sie meinem Control Überprüfung seine eigene Viewstate

von Immobilienbewertung geschieht? So meinen Sie nicht Control Auswertung C.C1 (was ich davon ausgehen, passiert nach C gebunden wurde)


ich wirklich zu schätzen Ihre Hilfe


DRITTE EDIT:

Es tut mir wirklich leid, dass du dir wieder Zeit genommen hast.Ich werde mein Bestes tun, um dies zu meinem letzten Edit zu machen.


Update() aufgerufen wird, sowohl in OnLoadComplete und, wenn der Datenbindung erfolgt. Innerhalb Update() wird folgender Satz auch ausgeführt:

this.ViewState["ParameterValue"] = actualValue; 

Also, wenn Update() aufgerufen wird, wenn die Datenbindung stattfindet, dann, was das bedeutet ist , dass, wenn auf dem nächsten Postback Update() in OnLoadComplete genannt wird, C.C1 und Control bereits gleiche Werte haben und somit

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

wird immer false zurück (wenn Update() in OnLoadComplete genannt wird), und so OnParameterChanged Ereignis wird nie 1 gefeuert werden? Wenn ja, das ich nicht um die Notwendigkeit zu sehen, Update() in OnLoadComplete aufzurufen!


viel verpflichtet

+0

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

+0

Weitere Informationen zur Verfügung gestellt, mit etwas Code. – Ruslan

Antwort

2

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.

+0

Ich habe meine Fragen aktualisiert, falls Sie immer noch bereit sind zu helfen – SourceC

+0

Entschuldigen Sie, dass ich Sie wieder belästigt habe, aber ich habe einen anderen Schnitt gemacht, falls Sie Zeit finden. Wie auch immer, ich denke, dies ist der richtige Zeitpunkt, um zu fragen Leute zu benachrichtigen (die Art, wie ich Sie benachrichtige) über Kommentare über die Änderungen, die ich an meinem Thread vorgenommen habe, ist akzeptiertes Verhalten hier, oder wird das als Schädling betrachtet? Ich denke, das ist auch – SourceC

+0

Ich indirekt fragen, ob ich dich schäme :) – SourceC