web-dev-qa-db-fra.com

Ajouter ScriptManager à la page par programme?

Je développe un WebPart (il sera utilisé dans un environnement SharePoint, bien qu'il n'utilise pas le modèle objet) dans lequel je souhaite exposer AJAX fonctionnalité. En raison de la nature de l'environnement, L'ajout du gestionnaire de scripts directement à la page n'est pas une option et doit donc être ajouté par programme. J'ai tenté d'ajouter le contrôle ScriptManager à la page dans mon code de composant WebPart.

protected override void CreateChildControls()
{
    if (ScriptManager.GetCurrent(Page) == null)
    {
        ScriptManager sMgr = new ScriptManager();
        // Ensure the ScriptManager is the first control.
        Page.Form.Controls.AddAt(0, sMgr); 
    }
}

Cependant, lorsque ce code est exécuté, j'obtiens le message d'erreur suivant:

"La collection de contrôles ne peut pas être modifiée pendant les phases DataBind, Init, Load, PreRender ou Unload."

Existe-t-il un autre moyen d'ajouter le ScriptManager à la page à partir d'un WebPart, ou vais-je devoir simplement ajouter le ScriptManager à chaque page (ou page maître) qui utilisera le WebPart?

28
Kyle Trauberman

J'ai pu faire fonctionner cela en utilisant l'événement Init de la page:

protected override void OnInit(EventArgs e)
{
    Page.Init += delegate(object sender, EventArgs e_Init)
                 {
                     if (ScriptManager.GetCurrent(Page) == null)
                     {
                         ScriptManager sMgr = new ScriptManager();
                         Page.Form.Controls.AddAt(0, sMgr);
                     }
                 };
    base.OnInit(e);
}
41
Kyle Trauberman

J'ai fait ça et ça marche. Créez un espace réservé pour les contrôles:

<asp:PlaceHolder ID="WebGridPlaceholder" runat="server" >
</asp:PlaceHolder>

Ensuite, vous pouvez le faire dans CreateChildControls:

ScriptManager aSM = new ScriptManager();
aSM.ID = "GridScriptManager";
WebGridPlaceholder.Controls.Add(aSM);
6
daduffer

J'ai rencontré ce problème avec un contrôle de serveur ascx personnalisé. J'ai essayé de nombreuses solutions impliquant l'ajout de script aux événements OnInit du contrôle (qui ne sont exécutés qu'après avoir vérifié le contrôle ScriptManager), l'ajout de logique à l'intérieur des balises de serveur sur le contrôle et l'ajout d'éléments à environ tous les autres événements. Pas bien. J'ai finalement construit un contrôle qui hérite de ScriptManagerProxy et utilise ensuite le morceau de code de ktrauberman, légèrement modifié, pour ajouter un ScriptManager si nécessaire:

  public class ProxiedScriptManager : ScriptManagerProxy
  {
    protected override void OnInit(EventArgs e)
    {
      //double check for script-manager, if one doesn't exist, 
      //then create one and add it to the page
      if (ScriptManager.GetCurrent(this.Page) == null)
      {
        ScriptManager sManager = new ScriptManager();
        sManager.ID = "sManager_" + DateTime.Now.Ticks;
        Controls.AddAt(0, sManager);
      }

      base.OnInit(e);
    }
  }

Cela l'a fait pour moi.

5
Josh

J'ai eu le même problème de base que le reste d'entre vous. Je créais un contrôle ascx personnalisé et je voulais pouvoir ne pas me soucier de savoir si la page appelante avait déclaré le gestionnaire de script. J'ai contourné les problèmes en ajoutant ce qui suit au contorl ascx lui-même.

vers la page ascx -

<asp:PlaceHolder runat="server" ID="phScriptManager"></asp:PlaceHolder>

dans le panneau de mise à jour lui-même - oninit="updatePanel1_Init"

vers le fichier ascx.cs -

protected void updatePanel1_Init(object sender, EventArgs e)
{
     if (ScriptManager.GetCurrent(this.Page) == null)
     {
         ScriptManager sManager = new ScriptManager();
         sManager.ID = "sManager_" + DateTime.Now.Ticks;
         phScriptManager.Controls.AddAt(0, sManager);
     }
}

Merci à tous les autres membres de ce fil qui m'ont permis de démarrer.

5
Jon

C'est la seule façon dont je pourrais faire fonctionner mon panneau de mise à jour dans un composant Webpart compatible sharepoint 2007/2010. Nous utilisons une page maître 2010 avec un scriptmanager, mais une page maître 2007 sans.

.ascx

<asp:PlaceHolder ID="sMgr_place" runat="server" />
<asp:UpdatePanel runat="server" OnInit="updatePanel_Init"><ContentTemplate>
...
</ContentTemplate></asp:UpdatePanel>

.ascx.cs

public void updatePanel_Init(object sender, EventArgs e)
{
    if (ScriptManager.GetCurrent(Page) == null)
    {
        ScriptManager sMgr = new ScriptManager();
        sMgr.EnablePartialRendering = true;
        sMgr_place.Controls.Add(sMgr);
    }
}
2
Paul

J'ai utilisé ce code dans des contrôles Web personnalisés (.cs) qui contiennent des panneaux de mise à jour.

protected override void OnInit(EventArgs e)
{
    //...
    if (ScriptManager.GetCurrent(this.Page) == null)
    {
        ScriptManager scriptManager = new ScriptManager();
        scriptManager.ID = "scriptManager_" + DateTime.Now.Ticks;
        Controls.AddAt(0, scriptManager);
    }
    //...
}
1
user3311381

J'ai eu ce problème similaire et j'ai trouvé que le meilleur moyen était d'ajouter un ScriptManager global à la page principale, puis dans le code derrière vous pouvez y ajouter en:

ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference(virtualPath));
0
dkarzon