web-dev-qa-db-fra.com

Impossible de faire fonctionner ScriptManager.RegisterStartupScript dans WebControl imbriqué dans UpdatePanel

J'ai ce que je pense être un problème assez simple, mais pour la vie de moi, je ne vois pas mon problème. Le problème est lié à ScriptManager.RegisterStartupScript, quelque chose que j'ai utilisé plusieurs fois auparavant.

Le scénario que j'ai est que j'ai un contrôle Web personnalisé qui a été inséré dans une page. Le contrôle (et un ou deux autres) sont imbriqués dans un UpdatePanel. Ils sont insérés sur la page sur un PlaceHolder:

<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);
}

Il s'agit du seul panneau de mise à jour de la page.

Le contrôle nécessite un javascript initial pour qu'il fonctionne correctement. Le contrôle appelle:

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

et j'ai aussi essayé:

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

Le problème est que le script s'exécute correctement lorsque la page est affichée pour la première fois, mais ne se réexécute pas après une publication partielle. J'ai essayé ce qui suit:

  1. Appel de RegisterStartupScript à partir de CreateChildControls
  2. Appel de RegisterStartupScript depuis OnLoad/OnPreRender
  3. Utilisation de différentes combinaisons de paramètres pour les deux premiers paramètres (dans l'exemple ci-dessus, le contrôle est la page et le type est GetType (), mais j'ai essayé d'utiliser le contrôle lui-même, etc.).
  4. J'ai essayé d'utiliser des identifiants persistants et nouveaux (pas que je pense que cela devrait avoir un impact majeur dans les deux cas).
  5. J'ai utilisé quelques points d'arrêt et j'ai donc vérifié que la ligne d'enregistrement est appelée correctement.

La seule chose que je n'ai pas essayée est d'utiliser le UpdatePanel lui-même comme contrôle et type, car je ne pense pas que le contrôle devrait être au courant du panneau de mise à jour (et en tout cas il ne semble pas être un bon moyen d'obtenir la mise à jour panneau?).

Quelqu'un peut-il voir ce que je fais mal dans ce qui précède?

Merci :)


Eh bien, pour répondre à la requête ci-dessus - il semble que l'espace réservé perturbe en quelque sorte ScriptManager.RegisterStartupScript.

Lorsque je retire le contrôle de l'espace réservé et le code directement sur la page, le script Register fonctionne correctement (j'utilise également le contrôle lui-même comme paramètre).

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

Quelqu'un peut-il expliquer pourquoi un contrôle injecté sur un PlaceHolder empêcherait le ScriptManager d'enregistrer correctement le script? Je suppose que cela pourrait avoir quelque chose à voir avec le cycle de vie des contrôles dynamiques, mais j'apprécierais (à ma connaissance) s'il existe un processus correct pour ce qui précède.

33
Chris

Je pense que vous devriez en effet utiliser le Control overload du RegisterStartupScript.

J'ai essayé le code suivant dans un contrôle serveur:

[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);
    }
}

Ensuite dans ma page j'ai:

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

Où Placeholder1 est un espace réservé dans un panneau de mise à jour. L'espace réservé contient quelques autres commandes, y compris des boutons.

Cela s'est comporté exactement comme vous vous y attendez, j'ai reçu une alerte disant "Bonjour" à chaque fois que je charge la page ou que le panneau de mise à jour se met à jour.

L'autre chose que vous pourriez examiner est de vous connecter à certains des événements de cycle de vie de page qui sont déclenchés lors d'une demande de panneau de mise à jour:

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

L'événement PageRequestManager endRequestHandler se déclenche chaque fois qu'un panneau de mise à jour termine sa mise à jour - cela vous permettrait d'appeler une méthode pour configurer votre contrôle.

Mes seules autres questions sont:

  • Que fait réellement votre script?
  • Vraisemblablement, vous pouvez voir le script dans le code HTML en bas de la page (juste avant la balise de fermeture </form>)?
  • Avez-vous essayé de mettre quelques "alertes (" ici ");" appelle dans votre script de démarrage pour voir s'il est appelé correctement?
  • Avez-vous essayé Firefox et Firebug - cela signale-t-il des erreurs de script?
15
Zhaph - Ben Duguid

J'ai eu un problème en utilisant ceci dans un contrôle utilisateur (dans une page cela a bien fonctionné); le Button1 est à l'intérieur d'un updatepanel, et le scriptmanager est sur le usercontrol.

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

Il semble maintenant que vous devez être prudent avec les deux premiers arguments, ils doivent référencer votre page, pas votre contrôle

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

Lorsque vous appelez ScriptManager.RegisterStartupScript, le paramètre "Control" doit être un contrôle qui se trouve dans un UpdatePanel qui sera mis à jour. Vous devez le changer pour:

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

La solution consiste à placer les scripts dans un fichier js extérieur (appelé "yourDynamic.js") et à réenregistrer le fichier à chaque fois que vous actualisez le panneau de mise à jour.

J'utilise ceci dans l'événement updatepanel_prerender:

ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "UpdatePanel1_PreRender", _
                   "<script type='text/javascript' id='UpdatePanel1_PreRender'>" & _
                   "include('yourDynamic.js');" & _
                   "removeDuplicatedScript('UpdatePanel1_PreRender');</script>" _
                   , False)

Dans la page ou dans une autre inclusion, vous aurez besoin de ce 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;
                }
            }
        }
    }
}

Assez cool, ah ... jejeje Cette partie de ce que j'ai posté il y a quelque temps ici .

J'espère que cette aide ... :)

1
Lucas

N'UTILISEZ PAS GUID pour la clé

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

et si vous voulez le faire, appelez quelque chose comme cette fonction

 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", "");
 }
1
ahmad sarkar

J'ai eu un problème avec Page.ClientScript.RegisterStartUpScript - je n'utilisais pas de panneau de mise à jour, mais le contrôle a été mis en cache. Cela signifiait que je devais insérer le script dans un Literal (ou pouvais utiliser un PlaceHolder) donc quand rendu du cache le script est inclus.

Une solution similaire pourrait fonctionner pour vous.

1
s_hewitt

Ce qui a fonctionné pour moi, c'est de l'enregistrer sur la page tout en spécifiant le type comme celui du UpdatePanel, comme ceci:

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

La valeur de paramètre "true" à la fin de ScriptManager.RegisterStartupScript ajoutera une balise JavaScript à l'intérieur de votre page:

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

Si la valeur est "false", elle injectera uniquement le script sans la balise --script--.

0
ZoharAdar

Parfois, il ne se déclenche pas lorsque le script contient une erreur de syntaxe, assurez-vous que le script et la syntaxe javascript sont corrects.

0
Prema Tiwari

J'ai essayé beaucoup de choses et j'ai finalement trouvé que le dernier paramètre doit être faux et vous devez ajouter <SCRIPT> tag au script Java:

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

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);
0
Steve