Asp.net 使用UpdatePanel以编程方式创建ScriptManager的UserControl是否可能?

Asp.net 使用UpdatePanel以编程方式创建ScriptManager的UserControl是否可能?,asp.net,ajax,updatepanel,user-controls,scriptmanager,Asp.net,Ajax,Updatepanel,User Controls,Scriptmanager,我想在UserControl中使用UpdatePanel。问题是该控件所在的.aspx页将没有ScriptManager。我需要在UserControl中创建ScriptManager。但是,如果使用UserControl,比如在页面上放置两次,那么放置ScriptManager将不起作用,因为您只能初始化ScriptManager一次 在其他需要ScriptManager的用户控件中,我使用的是AJAX工具包扩展,我能够使用以下代码: protected override void OnIni

我想在UserControl中使用UpdatePanel。问题是该控件所在的.aspx页将没有ScriptManager。我需要在UserControl中创建ScriptManager。但是,如果使用UserControl,比如在页面上放置两次,那么放置ScriptManager将不起作用,因为您只能初始化ScriptManager一次

在其他需要ScriptManager的用户控件中,我使用的是AJAX工具包扩展,我能够使用以下代码:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    Page.Init += new EventHandler(Page_Init);
}

void Page_Init(object sender, EventArgs e)
{
    if (Page.Form != null && ScriptManager.GetCurrent(Page) == null)
        Page.Form.Controls.AddAt(0, new ScriptManager());
}
…效果很好,但对于UpdatePanel案例来说不是这样

注意,我没有使用母版页


另一种方法是在UpdatePanel中以编程方式创建UserControl,我想这是不可能的。我试过几种不同的方法。你可能必须咬紧牙关,在你的页面上放一个脚本管理器

它不起作用的原因是什么?您是否从UpdatePanel获得需要ScriptManager的异常?您使用的是System.Web.Extensions 1.0还是3.5?我这么说是因为在3.5中对UpdatePanel进行了更改,导致其内容模板在OnInit之前实例化,所以我看不出有什么明显的原因说明它不起作用。如果出现异常,查看堆栈跟踪会很有帮助。

我遇到了同样的问题。问题是您需要在OnInit阶段之前添加scriptmanager——据我所知,它需要在preinit阶段完成。您可以通过添加覆盖负载看到这一点-我发现页面通过preinit ok,然后转到addedcontrol事件,它在或刚刚在之后,但这一点是有意义的,您需要一个scriptmanager被抛出。由于WUCs没有PreInit事件,我正在努力寻找如何从子usercontrol向Page.PreInit事件添加事件处理程序。即使是WUC构造函数也不会在该点之前触发,并且在构造函数中页面对象为null,因此无法将其添加到该点。即使在WUC的AddedControl阶段,您似乎仍然无法访问主页ScriptManager oSCM=ScriptManager.GetCurrentPage;返回null,因此在抛出错误之前,如果需要,您似乎无法添加scriptmanager

/编辑:- 据我所知,我在asp.net论坛上对此没有答案——令人惊讶的是,令人惊讶的是,WUC直到父级的preinit阶段之后才开始启动它的方法/事件,所以有两种方法可以做到这一点

1我认为这样做的方式是不将任何需要scriptmanager的内容放在设计器中,并将占位符放在需要这些内容的位置。然后在wuc加载中,使用ScriptManager.GetCurrent查看是否已经有一个,如果没有,则创建它。然后动态添加需要SCM的内容。大概是这样的:-

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="wucTestExample.ascx.cs" Inherits="wucTestExample" %> <asp:PlaceHolder ID="plcAJAX" runat="server" /> <asp:Label ID="lblGeneral" runat="server" Text="This is another label" /> ----------------code behind--------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class wucTestExample : System.Web.UI.UserControl { protected void Page_Load(object sender, EventArgs e) { ScriptManager oSCM = ScriptManager.GetCurrent(this.Page); if (oSCM == null) { oSCM = new ScriptManager(); oSCM.ID = "scmAJAX"; oSCM.EnablePartialRendering = true; this.plcAJAX.Controls.AddAt(0, oSCM); } UpdatePanel udpMain = new UpdatePanel(); udpMain.ID = "udpMain"; TextBox txtMain = new TextBox(); txtMain.ID = "txtMain"; // other attrbutes here Button btnPostback = new Button(); btnPostback.ID = "btnPostback"; btnPostback.Click += new EventHandler(btnPostback_Click); btnPostback.Text = "Partial Postback"; Label lblPostback = new Label(); lblPostback.ID = "lblPostback"; lblPostback.Text = "initial postback"; udpMain.ContentTemplateContainer.Controls.Add(txtMain); udpMain.ContentTemplateContainer.Controls.Add(btnPostback); udpMain.ContentTemplateContainer.Controls.Add(lblPostback); this.plcAJAX.Controls.Add(udpMain); } void btnPostback_Click(object sender, EventArgs e) { // implement button code here Label lblPostback = (Label)this.plcAJAX.FindControl("lblPostback"); if (lblPostback != null) { lblPostback.Text = String.Format("WUC POstback at : {0}", DateTime.Now.ToLongTimeString()); } } } 然后这样使用它:-

<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="TestExampleNoSCM.aspx.cs" Inherits="TestExampleNoSCM" %> <%@ Register Src="~/wucTestExample.ascx" TagName="wucTestExample" TagPrefix="ucTE" %> <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> <%--<asp:ScriptManager ID="scmAJAX" runat="server" />--%> <asp:Label ID="lblLoadTime" runat="server" /> <ucTE:wucTestExample ID="wucTestExample" runat="server" /> </asp:Content> ----------------code behind--------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class TestExampleNoSCM : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { this.lblLoadTime.Text = String.Format("Page load at: {0}",DateTime.Now.ToLongTimeString()); } } 因此,如果在父页面中注释或取消注释SCM,WUC仍然可以以任何方式工作

2我看到另一个选项,其中需要一个更新面板,程序员在设计器中创建所有控件,然后在创建SCM(如果需要)和UDP后在页面加载中循环它们,并在WUC UDP上添加所有控件,然后将其添加到占位符,但这让我觉得相当危险,因为它似乎是双重实例化控制,我认为它可能会回来咬他们的屁股

方法1的缺点是,以编程方式在updatepanel中创建所有内容需要更多的工作,但是如果您真的想构建一个独立的WUC,这似乎是您的代价,希望WUC不会那么复杂。就我个人而言,我认为在我的应用程序中,由于WUC不会在它之外使用,我只会确保在主页上需要的地方添加SCM

还有一个,最后一个,我想说的是-我看到有人说把它添加到母版页-这似乎是一个特别糟糕的主意,IMHO,除非你的应用程序中的每个页面都需要SCM,因为它会给你的页面添加一个全新的膨胀级别,这似乎不是一个好主意,因为ASP.NET似乎已经有了很好的膨胀级别…

解决方案:您可以通过检查当前页面是否还包含scriptmanager,在usercontrol中动态添加scriptmanager。以下是方法:

在UserControl ascx html中,输入以下内容:

<asp:PlaceHolder ID="pHolder" runat="server" />
有时需要动态定义ScriptManager。在我的例子中,我使用的是一个usercontrol,它将被放入不同的页面中,但其中一些页面已经包含ScriptManager,而另一些页面则不包含,那么我的usercontrol如何知道它是否应该定义自己的ScriptManager呢?上述代码的优点在于,只有当页面上还没有scriptmanager时,usercontrol才会添加scriptmanager

注意:如果使用较旧版本的Ajax,System.Web.UI.AjaxScriptManager可能会替换为System.Web.UI.ScriptManager。

如果页面上不存在ScriptManager,则不要动态添加ScriptManager,只需执行相反的操作:将ScriptManager添加到ASCX中,如果页面上已有ScriptManager,则将其删除。所以

protected override void OnInit(EventArgs e) {
    base.OnInit(e);
    AdjustScriptManager();
}

private void AdjustScriptManager() {
    if (ScriptManager.GetCurrent(Page) != null) {
        ScriptManager1 = null;
    }
}
更新:


不,在进一步测试之后,这将不起作用,因为ScriptManager1=null没有任何帮助。如果有办法做到这一点或删除页面控件,请发表评论。

只是一个方面,而不是代码有点重复。重写OnInit方法并添加Init事件处理程序。只需将代码放在Page_Init中覆盖的OnInit中?听起来您知道自己在做什么!如果你能找到解决办法,请告诉我!我上面编辑的一个警告是,以编程方式添加控件可能会增加viewstate等方面的复杂性。因此,我的boj工作只是向父级添加SCM,可能会在控件中添加注释,提及这可能是一个更好的选项,除非您需要该级别或自我依赖性/可移植性。不起作用。当用户控件包含UpdatePanel时,如果页面上没有ScriptManager,该控件甚至无法访问OnInit。在用户控件的构造函数中尝试这样做是行不通的,因为页面将为null。
protected override void OnInit(EventArgs e) {
    base.OnInit(e);
    AdjustScriptManager();
}

private void AdjustScriptManager() {
    if (ScriptManager.GetCurrent(Page) != null) {
        ScriptManager1 = null;
    }
}