2009-04-29 18 views
33

Estoy teniendo lo que creo que debería ser un problema bastante simple, pero por mi vida no puedo ver mi problema. El problema está relacionado con ScriptManager.RegisterStartupScript, algo que he usado muchas veces antes.No se puede obtener ScriptManager.RegisterStartupScript en WebControl anidado en UpdatePanel para trabajar

El escenario que tengo es que tengo un control web personalizado que se ha insertado en una página. El control (y uno o dos más) están anidados dentro de un UpdatePanel. Se insertan en la página en un marcador de posición:

<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 es el único panel de actualización en la página.

El control requiere que se ejecute algún javascript inicial para que funcione correctamente. Las llamadas de control:

ScriptManager.RegisterStartupScript(this, GetType(), 
            Guid.NewGuid().ToString(), script, true); 

y también he intentado:

ScriptManager.RegisterStartupScript(Page, Page.GetType(), 
            Guid.NewGuid().ToString(), script, true); 

El problema es que el script se ejecuta correctamente cuando se muestra por primera vez la página, pero no vuelve a funcionar después de una devolución de datos parcial. He intentado lo siguiente:

  1. Calling RegisterStartupScript de CreateChildControls
  2. Calling RegisterStartupScript de OnLoad/OnPreRender
  3. El uso de diferentes combinaciones de parámetros para los dos primeros parámetros (en el ejemplo anterior, el control es la página y Tipo GetType(), pero he intentado usar el control mismo, etc.).
  4. He intentado usar identificadores nuevos y persistentes (aunque no creo que esto tenga un impacto importante).
  5. He utilizado algunos puntos de interrupción y he verificado que la línea de registro se está llamando correctamente.

Lo único que no he probado es utilizar el UpdatePanel como Control y Type, ya que no creo que el control tenga en cuenta el panel de actualización (y en cualquier caso no parece haber un buena forma de obtener el panel de actualización?).

¿Alguien puede ver lo que podría estar haciendo mal en lo de arriba?

Gracias :)


Bueno, para responder a la consulta anterior - que parece como si el marcador de posición de alguna manera arruina la ScriptManager.RegisterStartupScript.

Cuando retiro el control del marcador de posición y lo codigo directamente en la página, la secuencia de comandos Register funciona correctamente (también estoy usando el control como parámetro).

 

ScriptManager.RegisterStartupScript(this, GetType(), Guid.NewGuid().ToString(), script, true); 

¿Alguien puede arrojar alguna luz sobre por qué un control se inyectó en un marcador de posición evitaría que el ScriptManager de registrar correctamente el guión? Supongo que esto podría tener algo que ver con el ciclo de vida de los controles dinámicos, pero agradecería (por mi propio conocimiento) si hay un proceso correcto para lo anterior.

Respuesta

14

Creo que debería estar utilizando el Control overload de RegisterStartupScript.

he probado el siguiente código en un control 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); 
    } 
} 

Luego, en mi página que tienen:

protected override void OnInit(EventArgs e){ 
    base.OnInit(e); 
    Placeholder1.Controls.Add(new AlertControl()); 
} 

Dónde PLACEHOLDER1 es un marcador de posición en un panel de actualización. El marcador de posición tiene un par de controles más, incluidos botones.

Esto se comportó exactamente como era de esperar, recibí una alerta que decía "Hola" cada vez que cargaba la página o causaba que el panel de actualización se actualizara.

La otra cosa que podría mirar es conectar con algunos de los eventos de la página de ciclo de vida que se disparan durante una solicitud de establecimiento de actualización:

Sys.WebForms.PageRequestManager.getInstance() 
    .add_endRequest(EndRequestHandler); 

Los fuegos PageRequestManager endRequestHandler evento cada vez que un panel de actualización completa su actualización - esto le permitiría llamar a un método para configurar su control.

Mis únicas otras preguntas son:

  • Lo que está haciendo realmente su guión?
  • Presumiblemente, puede ver la secuencia de comandos en el código HTML en la parte inferior de la página (justo antes de la etiqueta de cierre </form >)?
  • Ha intentado poner algunas "alertas" ("Aquí"); " llama en su script de inicio para ver si se está llamando correctamente?
  • ¿Has probado Firefox y Firebug? ¿Eso es informar de algún error de script?
+0

Hola Ben, gracias por la respuesta. Por el momento, el script simplemente activa una alerta, nada más. Es un control de cuadrícula, que hereda la cuadrícula de datos. Normalmente usaría Firefox/Bug, pero en este caso estoy trabajando en una aplicación exclusiva de IE (no es mi elección), no podré acceder a la pantalla en FF. Utilizando la barra de herramientas de IE Dev puedo examinar la página, pero el script no se ha vuelto a registrar en la devolución de datos. Me gusta la idea de PageRequestManager, aunque el script no se expone fácilmente a la página para llamar como controlador.Me gustan las ideas y las usaré para investigar más a fondo, gracias – Chris

10

Cuando llama a ScriptManager.RegisterStartupScript, el parámetro "Control" debe ser un control que se encuentra dentro de un UpdatePanel que se actualizará.Es necesario cambiarlo a:

ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(), script, true); 
+0

Sí, he intentado usar el control en sí, que está anidado dentro del UpdatePanel. El control se inserta en el marcador de posición, pero creo que esto debería estar bien. – Chris

1

La solución es poner los scripts en el archivo de un afuera js (deja llamada '' yourDynamic.js) y volver a registrar de archivo cada vez que se actualiza el UpdatePanel.

uso este en 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) 

En la página o en alguna otra opción de inclusión que necesitará esta 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; 
       } 
      } 
     } 
    } 
} 

bastante bonito, ah ... jejeje Este parte de lo que publiqué hace un tiempo here.

Espero que esto ayuda ... :)

+0

Hmmm, mecanismo interesante: puedo ver cómo sería útil en algunas circunstancias. No estoy 100% seguro de que esto lo resuelva, ya que cualquier js insertado a través del administrador de scripts está siendo ignorado por UpdatePanel; ni ​​siquiera puedo obtener una alerta ('hello world'); ¡correr! No cuando está incrustado en el marcador de posición en cualquier caso :(Lo ejecutará, siempre feliz de ser desaprobado :) – Chris

+0

Tenga en cuenta que aquí la inserción está hecha en realidad por javascript, eso es lo que lo hace tan dinámico. Déjame saber si funciona. – Lucas

+0

Ah ... y recuerda que la llamada al RegisterClientScriptBlock debe estar dentro del evento updatepanel prerrender ... :) – Lucas

1

que tenía un problema con Page.ClientScript.RegisterStartUpScript - no estaba usando un panel de actualización, pero el control se almacena en caché. Esto significaba que tenía que insertar la secuencia de comandos en un Literal (o podría usar un PlaceHolder), por lo que cuando se procesa desde la memoria caché, se incluye la secuencia de comandos.

Una solución similar podría funcionar para usted.

+0

Gracias - Investigaré la cadena literal, podría ser una buena solución. Estoy usando una técnica de inserción diferente ya que estoy usando métodos estáticos de System.Web.Ui.ScriptManager, no del mecanismo Page.ClientScript – Chris

0

que probar muchas cosas y finalmente encontraron que el último parámetro debe ser falsa y debe agregar <SCRIPT> etiqueta para la escritura de Java:

string script = "<SCRIPT>alert('hello!');< /SCRIPT>"; 

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**); 
+2

El ajuste verdadero para el último parámetro agrega automáticamente las etiquetas de secuencia de comandos. – cjk

33

tuve un problema usando esto en un control de usuario (en una página que funcionó bien); el Button1 está dentro de un updatepanel, y el scriptmanager está en el usercontrol.

protected void Button1_Click(object sender, EventArgs e) 
{ 
    string scriptstring = "alert('Welcome');"; 
    ScriptManager.RegisterStartupScript(this, this.GetType(), "alertscript", scriptstring, true); 
} 

Ahora parece que tiene que tener cuidado con los dos primeros argumentos, es necesario hacer referencia a su página, no su control de

ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alertscript", scriptstring, true); 
0

Lo que funcionó para mí, es el registro en la página, mientras especificando el tipo que la del UpdatePanel, así:

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) Guid.NewGuid().ToString(), myScript, true); 
0

a veces se duerma fuego cuando el guión tiene algún error de sintaxis, asegúrese de que el guión y Javascript sintaxis es correcta.

+0

más de un comentario –

1

no uso GUID para Key

ScriptManager.RegisterClientScriptBlock(this.Page, typeof(UpdatePanel) 
     Guid.NewGuid().ToString(), myScript, true); 

y si quieres hacer eso, llamada parecida a la función

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", ""); 
} 
0
ScriptManager.RegisterStartupScript(this, this.GetType(), Guid.NewGuid().ToString(),script, true); 

El valor de parámetro "verdadero" al final de ScriptManager.RegisterStartupScript agregará una etiqueta de JavaScript dentro de su página:

<script language='javascript' defer='defer'>your script</script > 

Si el valor será "falso", inyectará solo el script sin la etiqueta --script--.

Cuestiones relacionadas