28

我正在开发一个我想在其中公开 AJAX 功能的 WebPart(它将在 SharePoint 环境中使用,尽管它不使用对象模型)。由于环境的性质,将脚本管理器直接添加到页面是不是一个选项,因此必须以编程方式添加。我试图将 ScriptManager 控件添加到我的 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); 
    }
}

但是,执行此代码时,我收到以下错误消息:

“在 DataBind、Init、Load、PreRender 或 Unload 阶段不能修改控件集合。”

是否有另一种方法可以将 ScriptManager 从 WebPart 添加到页面,或者我是否必须将 ScriptManager 添加到将使用 WebPart 的每个页面(或母版页)?

4

7 回答 7

41

通过使用 Page 的 Init 事件,我能够让它工作:

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);
}
于 2008-10-08T18:48:59.140 回答
7

我和你们其他人有同样的基本问题。我正在创建一个自定义 ascx 控件,并且希望能够不用担心调用页面是否声明了 scriptmanager。我通过将以下内容添加到 ascx contorl 本身来解决这些问题。

到 ascx 页面 -

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

在更新面板本身 -oninit="updatePanel1_Init"

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

感谢这个线程中让我开始的所有其他人。

于 2009-11-19T05:05:40.910 回答
6

我已经做到了,并且有效。为控件创建一个占位符:

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

然后您可以在 CreateChildControls 中执行此操作:

ScriptManager aSM = new ScriptManager();
aSM.ID = "GridScriptManager";
WebGridPlaceholder.Controls.Add(aSM);
于 2008-12-05T23:27:33.127 回答
5

我在使用自定义 ascx 服务器控件时遇到了这个问题。我尝试了许多解决方案,包括将脚本添加到控件的 OnInit 事件(直到它检查 ScriptManager 控件之后才会执行)、在控件上的服务器标记内添加逻辑,以及在每个其他事件中添加内容。不好。我最终构建了一个继承自 ScriptManagerProxy 的控件,然后使用 ktrauberman 的一段代码,稍作修改,在需要时添加一个 ScriptManager:

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

那是为我做的。

于 2009-09-17T20:55:09.040 回答
2

这是我可以让我的更新面板在 sharepoint 2007 / 2010 兼容的 webpart 中工作的唯一方法。我们使用带有脚本管理器的 2010 母版页,但没有使用 2007 版母版页。

.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);
    }
}
于 2011-04-11T17:57:17.843 回答
1

我在包含更新面板的自定义 Web 控件 (.cs) 中使用了此代码。

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);
    }
    //...
}
于 2014-02-14T18:32:28.957 回答
0

我遇到了类似的问题,发现最好的方法是将全局 ScriptManager 添加到母版页,然后在后面的代码中添加:

ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference(virtualPath));
于 2009-03-26T02:33:44.287 回答