添加到“自定义控件”时,UpdatePanel 的触发器消失

发布于 2024-10-06 07:15:37 字数 3347 浏览 0 评论 0原文

基本上,简而言之,问题在于,一旦我将 UpdatePanel 动态生成的触发器添加为自定义控件的子级,就无法再找到它们(通过 ASP.NET)。

由于我正在处理的代码量相当大,因此我以较小的规模重新创建了问题,这将使调试变得更容易。

我脸上抛出的错误是:

在 UpdatePanel 'updatePanel' 中找不到触发器的 ID 为 'theTrigger' 的控件。

我不确定“自定义控件”的这种实现是否是正确的方法,但我没有编写原始的实现:我正在使用以前的开发人员编写的代码,我无法对其进行大量修改。这对我来说有点不寻常,但是,唉,这就是我得到的。

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestWeb.Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <asp:Panel runat="server" ID="panel">
      </asp:Panel>

      <asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>

      <asp:UpdatePanel runat="server" ID="updatePanel" UpdateMode="Conditional">
         <ContentTemplate> 
            <asp:Label ID="lblSomething" runat="server"></asp:Label>
         </ContentTemplate>
      </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestWeb
{
   public partial class Default : Page
   {
      protected void Page_Load(object sender, EventArgs e)
      {
         UselessTableWrapper table = new UselessTableWrapper();
         TableRow tr = new TableRow();
         TableCell td = new TableCell();

         LinkButton button1 = new LinkButton { ID = "theTrigger", Text = "Click Me" };
         button1.Click += button1_Click;
         td.Controls.Add(button1);

         tr.Controls.Add(td);
         table.AddRow(tr);

         panel.Controls.Add(table);
         // ### uncomment these lines (and comment the one above) to see it working
         // ### without the custom control
         /*
         Table realTable = new Table();
         realTable.Controls.Add(tr);
         panel.Controls.Add(realTable);
         */

         updatePanel.Triggers.Add(new AsyncPostBackTrigger { ControlID = "theTrigger", EventName = "Click" });
         scriptManager.RegisterAsyncPostBackControl(button1);
      }

      protected void button1_Click(object sender, EventArgs e)
      {
         lblSomething.Text = "Random number: " + new Random().Next(100);
         updatePanel.Update();
      }
   }
}

MyControl.cs

using System;
using System.Web.UI.WebControls;

namespace TestWeb
{
   public class UselessTableWrapper : WebControl
   {
      private Table table = new Table();

      protected override void OnPreRender(EventArgs e)
      {
         Controls.Add(table);
      }

      public void AddRow(TableRow row)
      {
         table.Controls.Add(row);
      }
   }
}

任何想法将不胜感激。

编辑

我已经尝试为此切换 OnPreRender 事件(在教程中找到):

protected override void RenderContents(HtmlTextWriter writer)
{
   writer.BeginRender();
   table.RenderControl(writer);
   writer.EndRender();
   base.RenderContents(writer);
}

...希望它能修复它,但事实并非如此。

Basically, in a nutshell, the problem is that dynamically generated triggers for an UpdatePanel can no longer be found (by ASP.NET) as soon as I add them as children of a custom control.

Since the amount of code I'm working on is quite substantial I've recreated the problem on a smaller scale, which will make it easier to debug.

The error thrown in my face is:

A control with ID 'theTrigger' could not be found for the trigger in UpdatePanel 'updatePanel'.

I'm not sure whether this implementation of a "custom control" is the right way to go about it, but I did not write the original implementation: I'm working with code written by a previous developer to which I cannot make large modifications. It looks a little unusual to me, but, alas, this is what I've been given.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestWeb.Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <asp:Panel runat="server" ID="panel">
      </asp:Panel>

      <asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>

      <asp:UpdatePanel runat="server" ID="updatePanel" UpdateMode="Conditional">
         <ContentTemplate> 
            <asp:Label ID="lblSomething" runat="server"></asp:Label>
         </ContentTemplate>
      </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TestWeb
{
   public partial class Default : Page
   {
      protected void Page_Load(object sender, EventArgs e)
      {
         UselessTableWrapper table = new UselessTableWrapper();
         TableRow tr = new TableRow();
         TableCell td = new TableCell();

         LinkButton button1 = new LinkButton { ID = "theTrigger", Text = "Click Me" };
         button1.Click += button1_Click;
         td.Controls.Add(button1);

         tr.Controls.Add(td);
         table.AddRow(tr);

         panel.Controls.Add(table);
         // ### uncomment these lines (and comment the one above) to see it working
         // ### without the custom control
         /*
         Table realTable = new Table();
         realTable.Controls.Add(tr);
         panel.Controls.Add(realTable);
         */

         updatePanel.Triggers.Add(new AsyncPostBackTrigger { ControlID = "theTrigger", EventName = "Click" });
         scriptManager.RegisterAsyncPostBackControl(button1);
      }

      protected void button1_Click(object sender, EventArgs e)
      {
         lblSomething.Text = "Random number: " + new Random().Next(100);
         updatePanel.Update();
      }
   }
}

MyControl.cs

using System;
using System.Web.UI.WebControls;

namespace TestWeb
{
   public class UselessTableWrapper : WebControl
   {
      private Table table = new Table();

      protected override void OnPreRender(EventArgs e)
      {
         Controls.Add(table);
      }

      public void AddRow(TableRow row)
      {
         table.Controls.Add(row);
      }
   }
}

Any ideas would be greatly appreciated.

Edit

I've tried switching the OnPreRender event for this (found in a tutorial):

protected override void RenderContents(HtmlTextWriter writer)
{
   writer.BeginRender();
   table.RenderControl(writer);
   writer.EndRender();
   base.RenderContents(writer);
}

... hoping that it would fix it, but it does not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼眸里的那抹悲凉 2024-10-13 07:15:37

这是我从后面的代码加载 aspx 控件内的 ascx Web 控件所采取的方法。

在控件中:

namespace dk_admin_site.Calculations
{
    public partial class AssignedFieldCalculation : System.Web.UI.UserControl
    {
        public static AssignedFieldCalculation LoadControl(Calculation initialData)
        {
            var myControl = (AssignedFieldCalculation) ((Page) HttpContext.Current.Handler).LoadControl(@"~\\Calculations\AssignedFieldCalculation.ascx");
            myControl._initialData = initialData;
            return myControl;
        }

        private Calculation _initialData;
        public Calculation Data { get { return _initialData; } }
        protected void Page_Load(object sender, EventArgs e) {}
    }
}

在Web表单中代码后面:

protected void Page_Load(object sender, EventArgs e)
{

    if (this.IsPostBack)
    {
        if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnRemoveCalculationFromField"))
        {
            //do something on the postback
        }
        else if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && (ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationUp") || ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationDown")))
        {
            //do something on the postback
        }
    }


    foreach (Calculation calc in calculationCollection)
    {
        AssignedFieldCalculation asCalc = AssignedFieldCalculation.LoadControl(calc);
        asCalc.ID = "calc" + calc.UniqueXKey;
        pnlFieldCalculations.Controls.Add(asCalc);

        foreach (Control ct in asCalc.Controls)
        {
            if (ct.ID == "btnMoveCalculationDown" || ct.ID == "btnMoveCalculationUp" || ct.ID == "btnRemoveCalculationFromField")
            {
                ScriptManager1.RegisterAsyncPostBackControl(ct);
            }
        }
    }
}

需要注意的几点:
将每个控件添加到 asp:Panel(称为 pnlFieldCalculations)时,需要使每个控件 ID 唯一。
LoadControl 方法允许您传递初始参数

this is the approach that I've taken with loading a ascx web control inside an aspx control from the code behind.

In the control:

namespace dk_admin_site.Calculations
{
    public partial class AssignedFieldCalculation : System.Web.UI.UserControl
    {
        public static AssignedFieldCalculation LoadControl(Calculation initialData)
        {
            var myControl = (AssignedFieldCalculation) ((Page) HttpContext.Current.Handler).LoadControl(@"~\\Calculations\AssignedFieldCalculation.ascx");
            myControl._initialData = initialData;
            return myControl;
        }

        private Calculation _initialData;
        public Calculation Data { get { return _initialData; } }
        protected void Page_Load(object sender, EventArgs e) {}
    }
}

in the web form code behind:

protected void Page_Load(object sender, EventArgs e)
{

    if (this.IsPostBack)
    {
        if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnRemoveCalculationFromField"))
        {
            //do something on the postback
        }
        else if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && (ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationUp") || ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationDown")))
        {
            //do something on the postback
        }
    }


    foreach (Calculation calc in calculationCollection)
    {
        AssignedFieldCalculation asCalc = AssignedFieldCalculation.LoadControl(calc);
        asCalc.ID = "calc" + calc.UniqueXKey;
        pnlFieldCalculations.Controls.Add(asCalc);

        foreach (Control ct in asCalc.Controls)
        {
            if (ct.ID == "btnMoveCalculationDown" || ct.ID == "btnMoveCalculationUp" || ct.ID == "btnRemoveCalculationFromField")
            {
                ScriptManager1.RegisterAsyncPostBackControl(ct);
            }
        }
    }
}

A few things to note:
You need to make each control ID unique when adding it to the asp:Panel (called pnlFieldCalculations).
The LoadControl method allows you to pass initial arguments

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文