UserControl与UpdatePanel以编程方式创建ScriptManager可能吗?

时间:2009-07-09 16:40:00

标签: asp.net ajax updatepanel user-controls scriptmanager

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

在我需要ScriptManager的其他UserControl中(我使用的是AJAX Toolkit Extensions)我能够使用这段代码:

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。)

5 个答案:

答案 0 :(得分:0)

我不认为这是可能的。我尝试了几种不同的方法。您可能需要咬紧牙关并在您的页面中放置一个脚本管理器。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我遇到了同样的问题。问题是你需要在OnInit阶段之前添加scriptmanager - 据我所知,它需要在preinit阶段完成。你可以通过添加一些覆盖来看到这一点 - 我发现页面已经通过preinit确定了,然后进入了addcontrol事件,它是在(或者只是之后,但这一点有道理)“你需要一个脚本管理器“被抛出。我很难找到如何从子用户控件向Page.PreInit事件添加事件处理程序,因为WUC没有PreInit事件。甚至WUC构造函数也不会在该点之前触发,并且在构造函数中,页面对象为null,因此您无法在那里添加它。即使在WUC的AddedControl阶段,你似乎仍然无法访问主页面(ScriptManager oSCM = ScriptManager.GetCurrent(Page);返回null)所以你似乎无法添加scriptmanager,如果你在抛出错误之前需要。

/编辑: - 据我所知(我在asp.net论坛上没有回答这个问题 - 惊讶,惊讶)WUC在父母的preinit阶段之后才开始踢它的方法/事件,所以有2个这样做的方法。

1)我认为我这样做的方式是不在设计师中放置任何需要脚本管理器的内容,并将占位符放在需要这些内容的地方。然后在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上的所有控件,然后将其添加到占位符,但这让我觉得相当危险,因为它似乎是双实例化控制,我认为它可能会回来咬他们的屁股... < / p>

方法1的缺点是,以编程方式在updatepanel中创建所有内容的工作量更大,但如果你真的想建立一个自我依赖的WUC,这似乎是你的代价(希望WUC不应该是这很复杂,无论如何)。就个人而言,我认为在我的应用程序中(因为WUC不会在它之外使用)我只是确保在主页上需要添加SCM。

另一个,最后,请注意我会投入 - 我见过有人说“将它添加到母版页” - 这似乎是一个特别糟糕的主意,恕我直言,除非每个页面在您的应用程序中需要SCM,因为它会为您的页面添加一个全新的膨胀程度,这似乎不是一个好主意,因为ASP.NET似乎已经具有良好的膨胀程度......

答案 3 :(得分:0)

如果页面上没有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;
    }
}

更新:

Nah,经过进一步测试后,这将无效,因为ScriptManager1 = null没有任何帮助。如果有办法(或删除页面控件),请发表评论。

答案 4 :(得分:-1)

解决方案:可以在用户控件中动态添加脚本管理器,方法是检查当前页面是否已包含ScriptManager。以下是:)

在UserControl(ascx)html中输入:

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

在后面的代码(ascx.cs)中:

    //insert Scriptmanager dynamically only IF it does not already exist
     private void createScriptManager(System.EventArgs e)
    {
        // the GetCurrent() method will return a ScriptManager from the Page
        if (System.Web.UI.AjaxScriptManager.GetCurrent(this.Page) == null)
        {
            System.Web.UI.AjaxScriptManager manager = new System.Web.UI.AjaxScriptManager();
            manager.EnablePartialRendering = true;
            pHolder.Controls.Add(manager);
        }
    }

    // call the above method from the usercontrol's OnInit
    override protected void OnInit(EventArgs e)
    {
        //
        // CODEGEN: This call is required by the ASP.NET Web Form Designer.
        //
        createScriptManager(e);
        base.OnInit(e);
    }

有时需要动态定义ScriptManager。在我的情况下,我使用的是一个将被放入不同页面的usercontrol,但是这些页面中的一些已经包含了ScriptManager而有些页面没有,所以我的usercontrol将如何知道它是否应该定义自己的ScriptManager?以上代码的优点在于,只有在页面上没有脚本管理器时,usercontrol才会添加脚本管理器。

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