【问题标题】:Adding Dynamic Controls in ASP.NET在 ASP.NET 中添加动态控件
【发布时间】:2013-09-11 01:12:31
【问题描述】:

在我看来,在 ASP.NET Web 窗体中动态添加控件存在固有的困难。具体来说,要在ViewState 中包含动态添加的控件,并使其事件正确连接等等,建议在Page_PreInit 事件期间添加这些控件。

也就是说,很多时候我们可能希望根据事件添加此类控件,例如用户单击按钮。控制特定事件(如 Click 事件)始终在 Init 之后运行,甚至在 Load 之后运行。假设如下.aspx....

 <form id="form1" runat="server">
    <div>
      <asp:PlaceHolder ID="phAddresses" runat="server"></asp:PlaceHolder>
       <br /><br />
        <asp:Button ID="btnAddAddress" runat="server" Text="Add Another Address" OnClick="btnAddAddress_Click" />

...以及下面的 .aspx.cs....

private static List<AddressUserControl> addresses = new List<AddressUserControl>();




protected void Page_PreInit(object sender, EventArgs e)
  {

   foreach (AddressUserControl aCntrl in addresses)
    {
      phAddresses.Controls.Add(aCntrl);
       // Helper to find button within user control
     addressButtonControl = findAddressControlRemoveButton(aCntrl);
     addressUserControlButton.ID = "btnRemoveAddress" + addressCount;
     addressUserControlButton.Click += new EventHandler(addressUserControlButton_Click);
     addressCount++;
    }
  }

 protected void btnAddAddress_Click(object sender, EventArgs e)
 {
  AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx")                 as    AddressUserControl;
 addresses.Add(aCntrl);
 }

现在在上述情况下,显示的用户控件的数量总是比用户实际添加的数量少一,因为 Click 事件直到 PreInit 之后才会运行,此时控件必须添加到占位符。我必须在这里遗漏一些东西,因为这似乎是 ASP 生命周期所固有的,并且需要一些“hack”或其他。

编辑 - 是的,出于某种原因,我在 btnAddress_Click() 期间添加的 EventHandlers 不会运行,只有我在 Page_Init 期间添加的 EventHandlers 或在标记中以声明方式添加。这就是我试图做的......

protected void btnAddAddress_Click(object sender, EventArgs e)
 {
   AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
  addresses.Add(aCntrl);
  phAddresses.Controls.Add(aCntrl);
  findAddressControlRemoveButton(aCntrl);
  addressUserControlButton.ID = "btnRemoveAddress" + addresses.Count;

                ///////////////////////////////////////////////////////////////////////////////////
                // ADDED EVENT HANDLER HERE
                //////////////////////////////////////////////////////////////////////////////////////
  addressUserControlButton.Click += new E ventHandler(addressUserControlButton_Click);

  }

...但事件不会像我所说的那样触发。有什么想法吗?

编辑 - 这是我的 AddressUserControl 的标记。文件背后的代码没有逻辑

<%@ Control Language="C#" ClassName="AddressUserControl" AutoEventWireup="true" CodeBehind="AddressUserControl.ascx.cs" Inherits="XFAWithUserControl.UserControls.AddressUserControl" %>


    <asp:Panel ID="pnlAddressForm" runat="server">
        <asp:Label ID="lblStreet" runat="server" Text="Street Address"></asp:Label>
           <asp:TextBox ID="txtStreet" runat="server"></asp:TextBox>
             <br /><br />
            <asp:Label ID="lblCity" runat="server" Text="City"></asp:Label>
            <asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
            <br /><br />
            <asp:Label ID="lblState" runat="server" Text="State"></asp:Label>
            <asp:TextBox ID="txtState" runat="server"></asp:TextBox>
            <br /><br />
            <asp:Label ID="lblZip" runat="server" Text="Zip"></asp:Label>
            <asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
            <br /><br />
            <asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" />
        </asp:Panel>

现在我对 btnRemoveAddress 的点击事件就是这样的傻事......

 private void addressUserControlButton_Click(object sender, EventArgs e)
  {
    Button thisButton = sender as Button;
    thisButton.Text = "Why Hello";
  }

但我的目标是让它删除关联的 AddressUserControl,以便用户可以通过单击按钮从页面中添加和/或删除任意数量的 AddressUserControl。

编辑 - 这是我现在所拥有的,但仍然无法正常工作

protected void btnAddAddress_Click(object sender, EventArgs e)
        {
            AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
            addresses.Add(aCntrl);
            phAddresses.Controls.Add(aCntrl);
            findAddressControlRemoveButton(aCntrl);
            addressUserControlButton.ID = "btnRemoveAddress" + addresses.Count;
            aCntrl.ChangeText += new EventHandler(addressUserControlButton_Click);
        }

private void addressUserControlButton_Click(object sender, EventArgs e)
{
    Button thisButton = sender as Button;
    thisButton.Text = "Why Hello";
}

AddressUserControl.ascx

<asp:Panel ID="pnlAddressForm" runat="server">
    <asp:Label ID="lblStreet" runat="server" Text="Street Address"></asp:Label>
    <asp:TextBox ID="txtStreet" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Label ID="lblCity" runat="server" Text="City"></asp:Label>
    <asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Label ID="lblState" runat="server" Text="State"></asp:Label>
    <asp:TextBox ID="txtState" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Label ID="lblZip" runat="server" Text="Zip"></asp:Label>
    <asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" OnClick="btnRemoveAddress_Click" />
</asp:Panel>

AddressUserControl.ascx.cs

public event EventHandler ChangeText;



   protected void Page_Load(object sender, EventArgs e)
    {

    }

    public void btnRemoveAddress_Click(object sender, EventArgs e)
    {
        if (this.ChangeText != null)
        {
            ChangeText(sender, e);
        }
    }

【问题讨论】:

    标签: c# asp.net dynamic user-controls webforms


    【解决方案1】:

    您需要将点击处理程序中的逻辑添加到面板的 Controls 集合以及控件列表中,如下所示:

    protected void btnAddAddress_Click(object sender, EventArgs e)
    {
        AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
        addresses.Add(aCntrl);
        phAddresses.Controls.Add(aCntrl);
    }
    

    更新:

    在您的用户控件中,您需要定义一个可以在承载用户控件的页面中定义的事件,如下所示:

    AddressUserControl.cs(代码隐藏):

    public event EventHandler RemoveAddress;
    
    protected void removeAddressUserControlButton_Click(object sender, EventArgs e)
    {
        // Find out if the event has been set, if so then call it
        if (this.RemoveAddress!= null)
        {
            RemoveAddress(sender, e);
        }
    }
    

    现在在您使用用户控件的页面上,执行以下操作:

    // Wire up the user control's event
    nameOfUserControl.RemoveAddress += new EventHandler(addressUserControlButton_Click);
    

    最后,实现addressUserControlButton_Click事件:

    protected void addressUserControlButton_Click(object sender, EventArgs e)
    {
        // Do your dynamic control creation here or whatever else you want on the page
    }
    

    【讨论】:

    • 啊是的,这是有道理的。但是...你能从 Click 内部连接一个事件处理程序吗?
    • 是的,这行得通,但我认为您还处于这样的位置,即您想要连接到最后添加的用户控件的任何事件在另一个回帖后才会生效
    • 是的:control.Event+=new EventHandler(event_handling_method);
    • 是的,这对我不起作用。我添加了行 addressUserControlButton.Click += new EventHandler(addressUserControlButton_Click);在 btnAddress_Click 但是当我单击按钮时 eventHandler 没有运行。它只为在 Page_Init 期间添加的事件处理程序运行
    • @MassStrike - 你想做aCntrl.RemoveAddress += new EventHandler(addressUserControlButton_Click);;一个事件处理程序可以处理多个用户控件的点击(处理程序的sender 参数将告诉您哪个用户控件生成了事件)。用户控件中的按钮单击连接在其自己的事件处理程序中,但该处理程序内部的逻辑通过公共事件调用页面以通知页面事件(它,页面,注册)发生并做出反应事件并对页面执行某些操作、加载数据、删除数据等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多