Aggiungere ScriptManager alla pagina a livello di codice?
-
06-07-2019 - |
Domanda
Sto sviluppando una WebPart (verrà utilizzata in un ambiente SharePoint, sebbene non utilizzi il modello a oggetti) in cui voglio esporre la funzionalità AJAX. A causa della natura dell'ambiente, l'aggiunta di Script Manager direttamente a la pagina non è un'opzione e quindi deve essere aggiunta a livello di codice. Ho tentato di aggiungere il controllo ScriptManager alla pagina nel mio codice 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);
}
}
Tuttavia, quando viene eseguito questo codice, viene visualizzato il seguente messaggio di errore:
" La raccolta dei controlli non può essere modificata durante le fasi DataBind, Init, Load, PreRender o Unload. "
Esiste un altro modo per aggiungere ScriptManager alla pagina da una WebPart, o dovrò semplicemente aggiungere ScriptManager a ciascuna pagina (o pagina master) che utilizzerà WebPart?
Soluzione
Sono stato in grado di farlo funzionare utilizzando l'evento Init di 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);
}
Altri suggerimenti
L'ho fatto e funziona. Crea un segnaposto per i controlli:
<asp:PlaceHolder ID="WebGridPlaceholder" runat="server" >
</asp:PlaceHolder>
Quindi puoi farlo in CreateChildControls:
ScriptManager aSM = new ScriptManager();
aSM.ID = "GridScriptManager";
WebGridPlaceholder.Controls.Add(aSM);
Ho riscontrato questo problema con un controllo server ascx personalizzato. Ho provato molte soluzioni che coinvolgono l'aggiunta di script agli eventi OnInit del controllo (che non viene eseguito fino a quando non verifica il controllo ScriptManager), aggiungendo la logica all'interno dei tag del server sul controllo e aggiungendo elementi su ogni altro evento. Non buono. Alla fine ho creato un controllo che eredita da ScriptManagerProxy e quindi utilizza il pezzo di codice di ktrauberman, leggermente modificato, per aggiungere uno ScriptManager se necessario:
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);
}
}
È stato per me.
Ho avuto lo stesso problema di base che il resto di voi ha avuto. Stavo creando un controllo ascx personalizzato e volevo essere in grado di non preoccuparmi se la pagina chiamante fosse stata dichiarata dallo scriptmanager. Ho risolto i problemi aggiungendo quanto segue al contorl ascx stesso.
alla pagina ascx -
<asp:PlaceHolder runat="server" ID="phScriptManager"></asp:PlaceHolder>
nel pannello di aggiornamento stesso - oninit="updatePanel1_Init"
al file 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);
}
}
Grazie a tutti gli altri in questa discussione che mi hanno iniziato.
Questo è l'unico modo in cui ho potuto far funzionare il mio pannello di aggiornamento in una webpart compatibile con sharepoint 2007/2010. Usiamo una pagina master 2010 con uno scriptmanager ma una pagina master 2007 senza una.
.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);
}
}
Ho usato questo codice nei controlli web personalizzati (.cs) che contengono pannelli di aggiornamento.
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);
}
//...
}
Ho avuto questo problema simile e ho scoperto che il modo migliore era quello di aggiungere uno ScriptManager globale alla pagina master, quindi nel codice dietro puoi aggiungerlo tramite:
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference(virtualPath));