简体   繁体   English

在ASP.NET中添加动态控件

[英]Adding Dynamic Controls in ASP.NET

It kind of seems to me that there is an inherent difficulty in dynamically adding controls in ASP.NET Web Forms. 在我看来,在ASP.NET Web窗体中动态添加控件存在固有的困难。 Specifically, for a dynamically added control to be included in the ViewState , and have it's events properly wired up and so forth it is suggested that these be added during the Page_PreInit event. 具体来说,要使动态添加的控件包含在ViewState ,并正确地Page_PreInit事件等,建议在Page_PreInit事件期间添加这些Page_PreInit

That said, many times we'll probably want to add such controls according to an event, such as a user clicking a button. 也就是说,很多时候我们可能想根据事件(例如用户单击按钮)添加此类控件。 Control specific events like Click events always run after Init, and even after Load. 诸如Click事件之类的控件特定事件始终在Init之后甚至在Load之后运行。 Supposed the following .aspx.... 假设以下.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" />

...and the following .aspx.cs.... ...以及以下.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);
 }

Now in the above situation the number of User Controls displayed is always one behind the number the user has actually added, because the Click event doesn't run until after PreInit, where controls must be added to the placeholder. 现在,在上述情况下,显示的用户控件数始终落后于用户实际添加的数量,因为Click事件要到PreInit之后才运行,在PreInit之后必须将控件添加到占位符。 I must be missing something here, because this seems inherent to the ASP lifecycle, and to require some 'hack' or other. 我必须在这里遗漏一些东西,因为这似乎是ASP生命周期所固有的,并且需要一些“ hack”或其他。

EDIT - Yeah for some reason EventHandlers I add during btnAddress_Click() won't run, only EventHandlers I add during Page_Init, or declaratively in markup. 编辑-是的,由于某些原因,我在btnAddress_Click()期间添加的EventHandlers将无法运行,只有我在Page_Init期间或以声明方式在标记中添加的EventHandlers无法运行。 This is what I tried to do... 这就是我试图做的...

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

  }

...but the event won't fire as I've said. ...但事件不会像我所说的那样触发。 Any ideas? 有任何想法吗?

EDIT - Here's the markup for my AddressUserControl. 编辑-这是我的AddressUserControl的标记。 There's no logic in the code behind file 文件背后的代码中没有逻辑

<%@ 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>

right now my click event for btnRemoveAddress is just something silly like this... 现在我对btnRemoveAddress的点击事件只是这样的愚蠢...

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

but my goal is to have it remove the associated AddressUserControl, so that a user can add and/or remove an arbitrary number of AddressUserControls from the page by clicking buttons. 但是我的目标是让它删除关联的AddressUserControl,以便用户可以通过单击按钮从页面添加和/或删除任意数量的AddressUserControls。

EDIT - Here's what I have now, still doesn't work 编辑-这是我现在所拥有的,仍然无法正常工作

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 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 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);
        }
    }

You need to have the logic in your click handler add to the panel's Controls collection as well as to the list of controls, like this: 您需要将点击处理程序中的逻辑添加到面板的Controls集合以及控件列表中,如下所示:

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

UPDATE: 更新:

In your user control, you need to define an event that can be defined in the page that hosts the user control, like this: 在用户控件中,您需要定义一个事件,该事件可以在承载用户控件的页面中定义,如下所示:

AddressUserControl.cs (code-behind): 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);
    }
}

Now on your page where you are using the user control, do this: 现在,在您使用用户控件的页面上,执行以下操作:

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

Finally, implement the addressUserControlButton_Click event: 最后,实现addressUserControlButton_Click事件:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM