UserControl с UpdatePanel программно создать ScriptManager возможно? - PullRequest
1 голос
/ 09 июля 2009

Я хотел бы использовать UpdatePanel в моем UserControl. Проблема в том, что на странице .aspx, на которую упал элемент управления, НЕ будет ScriptManager. Мне нужно будет создать ScriptManager в UserControl. Однако, если используется UserControl, скажем, дважды на странице, размещение ScriptManager не будет работать, потому что вы можете инициализировать ScriptManager только один раз.

В других пользовательских элементах управления, где мне был нужен ScriptManager (я использовал расширения AJAX Toolkit), я мог использовать этот код:

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.

Обратите внимание, я НЕ пользуюсь мастер-страницами

(Другой подход, о котором я думал, но не могу понять, как это сделать, - это программно создать UserControl внутри UpdatePanel.)

Ответы [ 5 ]

0 голосов
/ 16 января 2013

Вместо динамического добавления ScriptManager, если на странице его нет, просто сделайте наоборот: добавьте ScriptManager в свой ASCX и избавьтесь от него, если он уже есть на странице. Итак ...

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

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

UPDATE:

Нет, после дальнейшего тестирования это не сработает, так как ScriptManager1 = null ничего не помогает. Если есть способ сделать это (или удалить элемент управления Page), пожалуйста, оставьте комментарий.

0 голосов
/ 26 ноября 2010

Решение: вы можете динамически добавить скрипт-менеджер в usercontrol, проверив, не содержит ли текущая страница ScriptManager. Вот как:)

В html UserControl (ascx) поместите это:

<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 добавляет менеджер сценариев, только если его еще нет на странице.

Примечание: System.Web.UI.AjaxScriptManager можно заменить на System.Web.UI.ScriptManager, если вы используете более старую версию Ajax.

0 голосов
/ 16 июля 2009

По какой причине это не работает? Получаете ли вы исключение из UpdatePanel, что требуется ScriptManager? Вы используете System.Web.Extensions 1.0 или 3.5? Я говорю это потому, что в UpdatePanel было внесено изменение в 3.5, которое вызывает создание экземпляра шаблона контента до OnInit, поэтому я не вижу очевидной причины, по которой это не сработает. Если есть исключение, было бы полезно увидеть трассировку стека.

0 голосов
/ 29 июля 2009

У меня такая же проблема. Проблема в том, что вам нужно добавить скрипт-менеджер перед этапом OnInit - насколько я вижу, это нужно сделать на этапе preinit. Вы можете увидеть это, добавив множество переопределений - я обнаружил, что страница прошла через preinit, все в порядке, затем перешел к событию addcontrol, и было (или сразу после него, но этот момент имеет смысл), что «Вам нужен менеджер сценариев» "брошен. Я изо всех сил пытаюсь найти, как добавить обработчик события к событию Page.PreInit от дочернего usercontrol, поскольку у WUC нет события PreInit. Даже конструктор WUC не срабатывает до этой точки, и в конструкторе объект страницы имеет значение null, поэтому вы не можете добавить его туда. Даже на этапе AddedControl WUC вы все еще не можете получить доступ к главной странице (ScriptManager oSCM = ScriptManager.GetCurrent (Page); возвращает ноль), поэтому вы не можете добавить скрипт-менеджер, если вы надо, до того как ошибка выдаётся.

/ редактировать: - Насколько я понимаю (а я не получил ответа на это на форумах 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, прежде чем добавить это к метке-заполнителю, но это кажется мне довольно опасным, так как это выглядит как двойной экземпляр управления, и я думаю, что он может вернуться, чтобы укусить их за задницу ...

Недостаток метода 1 заключается в том, что для создания всего в вашей панели обновлений требуется больше программ, но если вы действительно хотите создать независимый WUC, это, похоже, ваша цена (и, надеюсь, WUC не следует это сложно, во всяком случае). Лично я думаю, что в моем приложении (поскольку WUC не будет использоваться вне его) я просто добавлю SCM, где это необходимо, на главной странице.

Еще одно, последнее замечание, которое я хотел бы упомянуть - я видел людей, говорящих «добавь это на главную страницу» - это, кажется, особенно плохая идея, ИМХО, если только каждая страница в Ваше приложение нуждается в SCM, так как оно добавит на страницы совершенно новый уровень раздувания, и это не очень хорошая идея, поскольку ASP.NET, похоже, уже имеет хороший уровень раздувания ...

0 голосов
/ 10 июля 2009

Я не думаю, что это возможно. Я пробовал это несколькими разными способами. Возможно, вам придется прикусить пулю и поставить скрипт-менеджер на своей странице.

...