Impossible d'obtenir ScriptManager.RegisterStartupScript dans WebControl imbriqué dans UpdatePanel pour qu'il fonctionne

StackOverflow https://stackoverflow.com/questions/802506

Question

J'ai ce que je pense devrait être un problème assez simple, mais pour ma vie, je ne peux pas voir mon problème. Le problème est lié à ScriptManager.RegisterStartupScript, quelque chose que j'ai utilisé à plusieurs reprises auparavant.

Selon mon scénario, un contrôle Web personnalisé 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 dans 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 l’exécution de javascript initial pour fonctionner 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 s'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 à partir de 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 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 UpdatePanel lui-même comme contrôle et type, car je ne pense pas que le contrôle devrait connaître le panneau de mise à jour (et dans tous les cas, il ne semble pas y avoir de moyen obtenir le panneau de mise à jour?).

Quelqu'un peut-il voir ce que je peux faire de 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é fausse le 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 en tant que paramètre).

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

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

Était-ce utile?

La solution

Je pense que vous devriez effectivement utiliser la surcharge de contrôle de la 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, notamment des boutons.

Ceci s’est comporté exactement comme vous le souhaiteriez, un message d’alerte me disant & "Bonjour &"; chaque fois que j'ai chargé la page ou que le panneau de mise à jour a été mis à jour.

Vous pouvez également vous connecter à certains événements du cycle de vie d'une 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 est déclenché chaque fois qu'un panneau de mise à jour termine sa update - cela vous permettrait d’appeler une méthode pour configurer votre contrôle.

Mes seules autres questions sont les suivantes:

  • Quel est votre script actuellement?
  • Vous pouvez probablement voir le script dans le code HTML au bas de la page (juste avant la balise < / form > fermeture)??
  • Avez-vous essayé de mettre quelques & «alert» (& «Ici &«;); & «; appelle dans votre script de démarrage pour voir s'il est appelé correctement?
  • Avez-vous essayé Firefox et Firebug , signalant des erreurs de script?

Autres conseils

J'ai eu un problème en utilisant cela dans un contrôle utilisateur (dans une page, cela fonctionnait bien); le Button1 est dans 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);  
}

Maintenant, il semble que vous deviez faire attention aux deux premiers arguments, ils doivent référencer votre page, pas votre contrôle

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

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

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

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’avais posté il ya quelque temps ici .

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

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

Une solution similaire pourrait fonctionner pour vous.

NE PAS utiliser le 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", "");
 }

Ce qui a fonctionné pour moi, c’est de l’inscrire sur la page en spécifiant le type comme celui de UpdatePanel, comme suit:

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

Parfois, il ne se déclenche pas lorsque le script a une erreur de syntaxe, assurez-vous que la syntaxe du script et de javascript est correcte.

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

Le " vrai " La valeur param à la fin du ScriptManager.RegisterStartupScript ajoutera une balise JavaScript dans votre page:

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

Si la valeur sera " false " il n'injectera que le script sans la balise --script--.

J'ai essayé beaucoup de choses et j'ai finalement trouvé que le dernier paramètre devait être faux et que vous deviez ajouter une <SCRIPT> balise au script java:

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

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), key, script, **false**);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top