title: Adding Dynamic Controls in ASP.NET
body: <p>It kind of seems to me that there is an inherent difficulty in dynamically adding controls in ASP.NET Web Forms. Specifically, for a dynamically added control to be included in the <code>ViewState</code>, and have it's events properly wired up and so forth it is suggested that these be added during the <code>Page_PreInit</code> event. </p>
  
  <p>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. Supposed the following .aspx....</p>
  
  <pre><code> &lt;form id="form1" runat="server"&gt;
      &lt;div&gt;
        &lt;asp:PlaceHolder ID="phAddresses" runat="server"&gt;&lt;/asp:PlaceHolder&gt;
         &lt;br /&gt;&lt;br /&gt;
          &lt;asp:Button ID="btnAddAddress" runat="server" Text="Add Another Address" OnClick="btnAddAddress_Click" /&gt;
  </code></pre>
  
  <p></p>
  
  <p>...and the following .aspx.cs....</p>
  
  <pre><code>private static List&lt;AddressUserControl&gt; addresses = new List&lt;AddressUserControl&gt;();
  
  
  
  
  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);
   }
  </code></pre>
  
  <p>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. I must be missing something here, because this seems inherent to the ASP lifecycle, and to require some 'hack' or other.</p>
  
  <p>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. This is what I tried to do...</p>
  
  <pre><code>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);
  
    }
  </code></pre>
  
  <p>...but the event won't fire as I've said. Any ideas?</p>
  
  <p>EDIT - Here's the markup for my AddressUserControl. There's no logic in the code behind file</p>
  
  <pre><code>&lt;%@ Control Language="C#" ClassName="AddressUserControl" AutoEventWireup="true" CodeBehind="AddressUserControl.ascx.cs" Inherits="XFAWithUserControl.UserControls.AddressUserControl" %&gt;
  
  
      &lt;asp:Panel ID="pnlAddressForm" runat="server"&gt;
          &lt;asp:Label ID="lblStreet" runat="server" Text="Street Address"&gt;&lt;/asp:Label&gt;
             &lt;asp:TextBox ID="txtStreet" runat="server"&gt;&lt;/asp:TextBox&gt;
               &lt;br /&gt;&lt;br /&gt;
              &lt;asp:Label ID="lblCity" runat="server" Text="City"&gt;&lt;/asp:Label&gt;
              &lt;asp:TextBox ID="txtCity" runat="server"&gt;&lt;/asp:TextBox&gt;
              &lt;br /&gt;&lt;br /&gt;
              &lt;asp:Label ID="lblState" runat="server" Text="State"&gt;&lt;/asp:Label&gt;
              &lt;asp:TextBox ID="txtState" runat="server"&gt;&lt;/asp:TextBox&gt;
              &lt;br /&gt;&lt;br /&gt;
              &lt;asp:Label ID="lblZip" runat="server" Text="Zip"&gt;&lt;/asp:Label&gt;
              &lt;asp:TextBox ID="txtZip" runat="server"&gt;&lt;/asp:TextBox&gt;
              &lt;br /&gt;&lt;br /&gt;
              &lt;asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" /&gt;
          &lt;/asp:Panel&gt;
  </code></pre>
  
  <p>right now my click event for btnRemoveAddress is just something silly like this...</p>
  
  <pre><code> private void addressUserControlButton_Click(object sender, EventArgs e)
    {
      Button thisButton = sender as Button;
      thisButton.Text = "Why Hello";
    }
  </code></pre>
  
  <p>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.</p>
  
  <p>EDIT - Here's what I have now, still doesn't work</p>
  
  <pre><code>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";
  }
  </code></pre>
  
  <p>AddressUserControl.ascx</p>
  
  <pre><code>&lt;asp:Panel ID="pnlAddressForm" runat="server"&gt;
      &lt;asp:Label ID="lblStreet" runat="server" Text="Street Address"&gt;&lt;/asp:Label&gt;
      &lt;asp:TextBox ID="txtStreet" runat="server"&gt;&lt;/asp:TextBox&gt;
      &lt;br /&gt;&lt;br /&gt;
      &lt;asp:Label ID="lblCity" runat="server" Text="City"&gt;&lt;/asp:Label&gt;
      &lt;asp:TextBox ID="txtCity" runat="server"&gt;&lt;/asp:TextBox&gt;
      &lt;br /&gt;&lt;br /&gt;
      &lt;asp:Label ID="lblState" runat="server" Text="State"&gt;&lt;/asp:Label&gt;
      &lt;asp:TextBox ID="txtState" runat="server"&gt;&lt;/asp:TextBox&gt;
      &lt;br /&gt;&lt;br /&gt;
      &lt;asp:Label ID="lblZip" runat="server" Text="Zip"&gt;&lt;/asp:Label&gt;
      &lt;asp:TextBox ID="txtZip" runat="server"&gt;&lt;/asp:TextBox&gt;
      &lt;br /&gt;&lt;br /&gt;
      &lt;asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" OnClick="btnRemoveAddress_Click" /&gt;
  &lt;/asp:Panel&gt;
  </code></pre>
  
  <p>AddressUserControl.ascx.cs</p>
  
  <pre><code>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);
          }
      }
  </code></pre>