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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UserControl与UpdatePanel以编程方式创建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。)

答案

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

另一答案

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

另一答案

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

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

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之前,然后将其添加到占位符,但这让我感到相当危险,因为它似乎是双实例化控制,我认为它可能会回来咬他们的屁股......

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

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

另一答案

如果页面上没有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没有任何帮助。如果有办法(或删除页面控件),请发表评论。

另一答案

解决方案:您可以通过检查当前页面是否还包含ScriptManager来动态地在usercontrol中添加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替换。

以上是关于UserControl与UpdatePanel以编程方式创建ScriptManager可能吗?的主要内容,如果未能解决你的问题,请参考以下文章

Ajax控件之ScriptManager与UpdatePanel用法

ScriptManager和UpdatePanel用法 (ajax)

ASP.NET使用UpdatePanel实现AJAX

序列化与反序列化存储updatepanel

属于 UserControl 子级的错误与 UserControl 而不是子级相关联

UpdatePanel 中的 FileUpload 控件而不刷新整个页面?