Não é possível obter ScriptManager.RegisterStartupScript em WebControl aninhado em UpdatePanel ao trabalho
-
03-07-2019 - |
Pergunta
Eu estou tendo o que eu acredito que deve ser um problema bastante simples, mas para a vida de mim eu não posso ver o meu problema. O problema está relacionado com ScriptManager.RegisterStartupScript, algo que eu tenho usado muitas vezes antes.
O cenário que tenho é que eu tenho um controle web personalizada que foi inserido em uma página. O controlo (e um ou dois outros) são encaixados dentro de um UpdatePanel. Eles são inseridos na página em um espaço reservado:
<asp:UpdatePanel ID="pnlAjax" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="placeholder" runat="server">
</asp:PlaceHolder>
...
protected override void OnInit(EventArgs e){
placeholder.Controls.Add(Factory.CreateControl());
base.OnInit(e);
}
Este é o único painel de atualização na página.
O controle requer algum javascript inicial ser executado para que ele funcione corretamente. As chamadas de controle:
ScriptManager.RegisterStartupScript(this, GetType(),
Guid.NewGuid().ToString(), script, true);
e eu também tentei:
ScriptManager.RegisterStartupScript(Page, Page.GetType(),
Guid.NewGuid().ToString(), script, true);
O problema é que o script é executado corretamente quando a página é exibida pela primeira vez, mas não executar novamente depois de um postback parcial. Eu tentei o seguinte:
- Chamando RegisterStartupScript de CreateChildControls
- Chamando RegisterStartupScript de OnLoad / OnPreRender
- Usando diferentes combinações de parâmetros para os dois primeiros parâmetros (no exemplo acima, o controle é da página eo tipo é GetType (), mas eu tentei usar o próprio controle, etc).
- Eu tentei usar ids persistentes e novas (não que eu acredito que este deve ter um grande impacto de qualquer forma).
- Eu usei alguns pontos de interrupção e assim por ter verificado que a linha Register está sendo chamado corretamente.
A única coisa que eu não tentei é usando o próprio UpdatePanel como o controle e Tipo, como eu não acredito que o controle deve estar ciente do painel de atualização (e em qualquer caso, não parece ser uma boa maneira de ficando o painel de atualização?).
Alguém pode ver o que eu poderia estar fazendo errado no exemplo acima?
Obrigado:)
Bem, para responder a consulta acima -. Que parece como se o espaço reservado de alguma forma, mexe-se o ScriptManager.RegisterStartupScript
Quando eu puxar o controle fora do espaço reservado e código-lo diretamente na página do Register script funciona correctamente (eu também estou usando o próprio controle como um parâmetro).
ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true);
Alguém pode lançar alguma luz sobre por que um controle injecta-se um espaço reservado impediria a ScriptManager de registrar corretamente o script? Eu estou supondo que isso pode ter algo a ver com o ciclo de vida de controles dinâmicos, mas gostaria de receber (para o meu próprio conhecimento) se houver um processo correto para o acima.
Solução
Eu acho que você deve realmente estar usando o Controle sobrecarga do RegisterStartupScript.
Eu tentei o seguinte código em um controle de servidor:
[ToolboxData("<{0}:AlertControl runat=server></{0}:AlertControl>")]
public class AlertControl : Control{
protected override void OnInit(EventArgs e){
base.OnInit(e);
string script = "alert(\"Hello!\");";
ScriptManager.RegisterStartupScript(this, GetType(),
"ServerControlScript", script, true);
}
}
Então, em minha página eu tenho:
protected override void OnInit(EventArgs e){
base.OnInit(e);
Placeholder1.Controls.Add(new AlertControl());
}
Onde PLACEHOLDER1 é um espaço reservado em um painel de atualização. O espaço reservado tem um casal de outros controles sobre nele, incluindo botões.
Esta comportou exatamente como seria de esperar, eu tenho um alerta dizendo "Olá" cada vez que eu carregar a página ou causado o painel de atualização para atualização.
A outra coisa que você poderia olhar é para ligar para alguns dos eventos de ciclo de vida página que são acionados durante um pedido de painel de atualização:
Sys.WebForms.PageRequestManager.getInstance()
.add_endRequest(EndRequestHandler);
O evento PageRequestManager endRequestHandler dispara cada vez que um painel de atualização completa a sua atualização -. isso permitirá que você chamar um método para configurar o controle
As minhas únicas outras perguntas são:
- O que é o seu script realmente fazendo?
- Provavelmente, você pode ver o script no HTML na parte inferior da página (logo antes da tag de fechamento )?
- Você já tentou colocar um "alerta de poucos (" aqui ");" chamadas em seu script de inicialização para ver se ele está sendo chamado corretamente?
- Você já tentou Firefox e Firebug -? É que relatar quaisquer erros de script
Outras dicas
Eu tive um problema usando isso em um controle de usuário (em uma página deste funcionou bem); o Button1 está dentro de um updatepanel
, eo scriptmanager
está no usercontrol
.
protected void Button1_Click(object sender, EventArgs e)
{
string scriptstring = "alert('Welcome');";
ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true);
}
Agora, parece que você tem que ter cuidado com os dois primeiros argumentos, eles precisam fazer referência a sua página, não seu controle
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true);
Quando você chama ScriptManager.RegisterStartupScript, o parâmetro "Control" deve ser um controle que está dentro de um UpdatePanel que será atualizado. Você precisa alterá-lo para:
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true);
A solução é colocar os scripts no arquivo de um fora js (permite chamada 'yourDynamic.js') e volte a registar toda de arquivo que você atualizar o updatepanel.
Eu uso isso em caso updatepanel_prerender:
ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _
"<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _
"include('yourDynamic.js');" & _
"removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _
, False)
Na página ou em algum outro incluem você vai precisar deste javascript:
// Include a javascript file inside another one.
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
for(var x=0;x<scripts.length;> {
if (scripts[x].getAttribute('src'))
{
if(scripts[x].getAttribute('src').indexOf(filename) != -1)
{
head.removeChild(scripts[x]);
break;
}
}
}
script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
// Removes duplicated scripts.
function removeDuplicatedScript(id)
{
var count = 0;
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
var firstScript;
for(var x=0;x<scripts.length;> {
if (scripts[x].getAttribute('id'))
{
if(scripts[x].getAttribute('id').indexOf(id) != -1)
{
if (count == 0)
{
firstScript = scripts[x];
count++;
}
else
{
head.removeChild(firstScript);
firstScript = scripts[x];
count = 1;
}
}
}
}
clearAjaxNetJunk();
}
// Evoids the update panel auto generated scripts to grow to inifity. X-(
function clearAjaxNetJunk()
{
var knowJunk = 'Sys.Application.add_init(function() {';
var count = 0;
var head = document.getElementsByTagName('head')[0];
var scripts = document.getElementsByTagName('script');
var firstScript;
for(var x=0;x<scripts.length;> {
if (scripts[x].textContent)
{
if(scripts[x].textContent.indexOf(knowJunk) != -1)
{
if (count == 0)
{
firstScript = scripts[x];
count++;
}
else
{
head.removeChild(firstScript);
firstScript = scripts[x];
count = 1;
}
}
}
}
}
Muito legal, ah ... hehehe Esta parte do que eu postei há algum tempo aqui .
Espero que isso ajuda ...:)
Eu tive um problema com Page.ClientScript.RegisterStartUpScript - eu não estava usando um painel de atualização, mas o controle foi armazenado em cache. Isso significava que eu tinha que inserir o script em um Literal (ou poderia usar um espaço reservado) para que quando processado a partir do cache do script está incluído.
A solução trabalho poderio semelhante para você.
Não use GUID para a chave
ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel)
Guid.NewGuid().ToString(), myScript, true);
e se você quiser fazer isso, chamar algo como esta função
public static string GetGuidClear(string x)
{
return x.Replace("-", "").Replace("0", "").Replace("1", "")
.Replace("2", "").Replace("3", "").Replace("4", "")
.Replace("5", "").Replace("6", "").Replace("7", "")
.Replace("8", "").Replace("9", "");
}
O que funcionou para mim, está registrando-o na enquanto especifica o tipo que o do UpdatePanel, assim:
ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true);
Às vezes isso não acontecer fogo quando o script tem algum erro de sintaxe, verifique se o script e sintaxe javascript está correto.
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script, true );
O "verdadeiro" valor param no final da ScriptManager.RegisterStartupScript irá adicionar uma tag JavaScript dentro de sua página:
<script language='javascript' defer='defer'>your script</script >
Se o valor será "false" que vai injetar somente o script witout a tag --script--.
Eu tento muitas coisas e, finalmente, descobriu que o último parâmetro deve ser falso e você deve adicionar tag <SCRIPT>
para o java script:
string script = "< SCRIPT >alert('hello!');< /SCRIPT>";
ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);