Se os controles são sempre binded a controles de fonte de dados na ordem em que são declaradas, em seguida,
-
05-09-2019 - |
Pergunta
A) Pergunta abaixo é baseada na suposição de que os controles estão sempre binded a controles de fonte de dados na ordem em que são declarados? Assim, em nosso exemplo SqlDataSource1 irá se conectar a fonte de dados antes de SqlDataSource2 e, portanto, lstCities será preenchida com valores antes de GridView1 , ea razão para isso é que lstcities foi declarada antes de GridView1 ?!
B) Em caso afirmativo, em seguida, quando faz exatamente ControlParameter recuperar um valor de DropDownList ? Eu supor que é depois de SqlDataSource1_Selected () manipulador de eventos e antes SqlDataSource2_Selecting () manipulador de eventos, mas quando exatamente?
Na página .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>
thanx
EDIT:
Se for uma nova postagem, no entanto, em seguida, os parâmetros vai ser carregado a partir de um estado de visualização na página do OnLoadComplete, mais uma vez, na ordem em que são declaradas.
Q1 - Vamos supor ControlParameter é obrigado a C1 propriedade de um controle C. Eu imaginaria que em postbacks ControlProperty seria sempre capaz de obter o valor de C.C1 de ViewState, não importa de que tipo C é, e mesmo se C tem ViewState desativada ?!
Q2 - Mas posso perguntar por que, se uma página é criada pela primeira vez, pode não um valor para ControlParameter também ser recuperado a partir viewstate? Afinal, os dados lstCities momento recupera da fonte de dados, lstCities.SelectedValue tem seu valor definido?
thanx companheiro
SEGUNDO EDIT:
Peço desculpas por não responder mais cedo, mas eu não sabia que você já respondeu. E quando o fiz, passei boa 20 minutos a tentar obter meus 3 braincells para funcionar corretamente, mas não tenho certeza se eu bem sucedido
A) Assim ControlParameter avalia C.C1 e, assim, recupera o valor da C.C1 depois C foi ligado?!
Q1 - ControlParameter só lê seu próprio estado e só para determinar se ele mudou
cheques A) Assim ControlParameter se o seu ViewState alterado (a fim de fogo OnParameterChanged evento) antes de ligação ocorre -> assim, ele verifica sua ViewState durante Page.OnLoadComplete. Mas como ControlParameter saber que sua ViewState mudou (ele vai saber em primeira postagem)? Afinal, desde a primeira vez que a página é criada ViewState do ControlParameter será sempre marcado como sujo, então como é que, de um postback para o outro, ControlParameter saber se o seu valor mudou entre postbacks?
B) Presumo cheques ControlParameter se o seu Viewstate alterado apenas para que ele possa disparar evento OnParameterChanged. Mas por que está a lidar com esse evento tão importante?
A primeira vez que uma avaliação da propriedade acontece é em Page.OnLoadComplete
Por avaliação da propriedade você quer dizer ControlParameter verificando seu próprio ViewState? Assim você faz ControlParameter não média avaliar C.C1 (que eu suponho que acontece depois C foi ligado)
Eu realmente aprecio a sua ajuda
EDIT TERCEIRO:
Eu realmente sinto muito por mais uma vez tomar o seu time.I farei o meu melhor para fazer este meu último Editar.
Update () é chamado tanto em OnLoadComplete e quando a ligação de dados ocorre. Dentro Update () a seguinte frase também é executado:
this.ViewState["ParameterValue"] = actualValue;
Então, se Update () é chamado quando a ligação de dados ocorre, então o que isso significa é que, quando no próximo update postback () é chamado em OnLoadComplete, C.C1 e ControlParameter já terá mesmos valores e, portanto,
if ((actualValue == null && storedValue != null)
|| (actualValue != null && actualValue != storedValue))
sempre retornará false (quando Update () é chamado em OnLoadComplete), e evento para OnParameterChanged nunca vai ser demitido? 1 Se assim for, o que não conseguem ver a necessidade de chamar Update () em OnLoadComplete!
muito obrigado
Solução
Sua primeira suposição é correta.
Para sua segunda pergunta, depende se é um post de volta ou não e / ou se estiver a vincular explicitamente. Se não for parte de trás pós e vinculativa acontece automaticamente, em seguida, a grosso modo, o valor do ControlParameter é recuperada quando DataSourceView chama Select no DataBind, logo antes do evento OnSelecting. A sequência para o gridview (e qualquer dado de controlo para esse efeito) é como se segue:
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
Assim, para cada controle em uma hierarquia de controle, o quadro chama recursivamente DataBind, que então desencadeia recuperação de parâmetros, OnSelecting, recuperação de dados, e OnSelected.
Se for uma nova postagem, no entanto, em seguida, os parâmetros vai ser carregado a partir de um estado de visualização na página do OnLoadComplete, mais uma vez, na ordem em que são declaradas.
É isso que você estava procurando?
Editar
Q1 - Vamos supor ControlParameter é obrigado a C1 propriedade de um controle C. Eu imaginaria que em postbacks ControlProperty seria sempre capaz de obter o valor de C.C1 de ViewState, não importa de que tipo C é, e mesmo se C tem ViewState desabilitado?!
Isso não é inteiramente como isso acontece ... Na parte traseira pós (e no pedido inicial para que o assunto), o estado de exibição de ControlParemeter só é avaliada para ver se ele mudou para que o evento OnParameterChanged poderia ser demitido. O valor real do ControlParameter é avaliada contra o controlo que aponta para (por meio de reflexo). No seu caso seria "C.C1". Agora, quando se lê C.C1, seu valor é mais provável ler a partir de um estado de exibição. Mas em nenhum momento faz o ControlParameter ler o estado de exibição do C diretamente.
Q2 - Mas posso perguntar por que, se uma página é criada pela primeira vez, pode não um valor para ControlParameter também ser recuperado a partir viewstate? Afinal, os dados lstCities momento recupera da fonte de dados, lstCities.SelectedValue tem seu valor definido?
Essa é a coisa, naquele momento (as primeiras cargas de página tempo) os lstCities não recuperar todos os dados ainda. A primeira vez que uma avaliação da propriedade acontece é em Page.OnLoadComplete, mas antes de qualquer DataBind (o que acontece pouco depois, quando Page.PreRenderRecursiveInternal é demitido).
Na forma bruta, tentando colocá-lo em um ciclo de vida de uma página:
...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
Segunda Editar
Assim ControlParameter avalia C.C1 e, assim, recupera o valor da C.C1 depois C foi ligado?!
Os valores Recupera ControlParameter sempre que for solicitado, que neste cenário acontece (indiretamente) em dois locais: OnLoadComplete e DataBind (desencadeada por PreRenderRecursiveInternal). Em OnLoadComplete, o C não estiver ligada. Em PreRenderRecursiveInternal, após DataBind, o C está ligado. Ambas as vezes ControlParameter é solicitado a ler C.C1. Talvez seguir ajudará ...
Aqui estão as classes e métodos de interesse em poucas palavras. Coloque-os em perspectiva do ciclo de página e espero que seja clara.
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
//...
}
}
cheques A) Assim ControlParameter se o seu ViewState mudou ...
Consulte o método UpdateValue acima para ver como ele usa ViewState.
B) Presumo cheques ControlParameter se o seu Viewstate alterado apenas para que ele possa disparar evento OnParameterChanged. Mas por que está a lidar com esse evento tão importante?
Eu não sei que é importante. Suponho que, como qualquer outro evento, ele permite que você acompanhe mudanças nas propriedades de parâmetros e agir em conformidade com as suas necessidades. Ele é demitido em muitos lugares, mas eu não vejo onde ninguém subscreve a ele. Então ...
Por avaliação da propriedade você quer dizer ControlParameter verificando seu próprio ViewState? Assim você faz ControlParameter não média avaliar C.C1 (que eu suponho que acontece depois C tem been bound)
Isso significa que o ControlParameter.UpdateValue é chamado, que verifica ViewState razões expostas, em seguida, chama ControlParameter.Evalue, que, em seguida, encontra um controle e recupera dados usando reflexão (Eval). Veja acima.
Third Editar
Eu presumo que por Atualização quer dizer UpdateValue.
Então, se Update () é chamado quando a ligação de dados ocorre, então o que isso significa é que, quando a próxima atualização de postagem () é chamado em OnLoadComplete, C.C1 e ControlParameter já terá mesmos valores ...
Não necessário. Você está esquecendo que o estado de exibição é carregado em LoadAllState e entre ele eo OnLoadComplete há mais seis etapas (ver ciclo de vida da página acima). Cada um desses pode modificar o valor do controle de origem (C.C1).
Digamos que você tenha C.C1 = "x" e fez um posto de volta. Agora, o estado de exibição para todos os controlos é carregado (LoadAllState). Se C.C1 armazenado de valor no estado de exibição, ele irá carregar "x". Em Page_Load (LoadRecursive) você decidir definir C.C1 = "y". Aqui C.C1 pode decidir armazenar "y" em seu estado de exibição ou não - é irrelevante. Em seguida, outros eventos seguem. Em seguida, vem OnLoadComplete. Desde SqlDataSource subscreve a este evento, que irá avaliar todos os parâmetros associados (LoadCompleteEventHandler) e, uma vez que você fez a mudança C.C1 mas estado de exibição do ControlParameter não, o
if ((actualValue == null && storedValue != null)
|| (actualValue != null && actualValue != storedValue))
this.OnParameterChanged();
retornará verdadeiro e OnParameterChanged será demitido. By the way, há pelo menos dez outros lugares onde este evento é acionado. Ele não joga um papel grande (se houver) na ligação de dados e processo de recuperação de propriedade.