On an ASP.NET web page, I have an UpdatePanel. Inside this UpdatePanel, I have an “Add” button which dynamically adds any number of a User Control that I have created to a PlaceHolder. The User Control contains a label, a button, and a 3rd-party control. The button inside the User Control is for removing that particular User Control from the parent panel. Both the “Add” and “Remove” functionality work correctly. However, the event handler on the Add button sometimes stops working with no apparent pattern or cause. If I add 2 UCs and remove 1, sometimes the Add button continues to work and sometimes it doesn’t. Any step toward finding a cause would be helpful.
For context, the UCs are called “Whereas” because they are WHEREAS clauses in resolutions. Here is the code, cut down to relevant content only:
Edit.aspx
...
<asp:ScriptManager ID="sm1" runat="server"></asp:ScriptManager>
<asp:Panel ID="pnlMain" runat="server">
<div class="form-horizontal">
<asp:UpdatePanel ID="upnlWhereas" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="phWhereas" runat="server"></asp:PlaceHolder>
<div class="control-group">
<asp:Label ID="lblAddWhereas" AssociatedControlID="btnAdd1Whereas" CssClass="control-label" runat="server"></asp:Label>
<div class="controls">
<asp:Button ID="btnAdd1Whereas" CssClass="btn" UseSubmitBehavior="false" Text="Add Whereas" runat="server" />
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</asp:Panel>
...
Edit.aspx.vb (class is Edit2)
...
Private Property ControlsList As List(Of String)
Get
If ViewState("ControlsList") Is Nothing Then
ViewState("ControlsList") = New List(Of String)
End If
Return CType(ViewState("ControlsList"), List(Of String))
End Get
Set(ByVal Value As List(Of String))
ViewState("ControlsList") = Value
End Set
End Property
Private ReadOnly Property NextID As Integer
Get
Return ControlsList.Count + 1
End Get
End Property
Protected Overrides Sub LoadViewState(savedState As Object)
MyBase.LoadViewState(savedState)
For Each waID As String In ControlsList
Dim NewWhereas As Whereas
NewWhereas = Me.LoadControl("~/UserControls/Whereas.ascx")
NewWhereas.ID = waID
phWhereas.Controls.Add(NewWhereas)
AddHandler NewWhereas.OnRemoveWhereasClick, AddressOf Whereas_OnRemoveWhereasClick
Next
End Sub
...
Private Sub btnAdd1Whereas_Click(sender As Object, e As System.EventArgs) Handles btnAdd1Whereas.Click
Dim NewWhereas As Whereas
NewWhereas = Me.LoadControl("~/UserControls/Whereas.ascx")
NewWhereas.ID = "wa" + NextID.ToString
phWhereas.Controls.Add(NewWhereas)
ControlsList.Add(NewWhereas.ID)
End Sub
Private Sub Whereas_OnRemoveWhereasClick(ByVal sender As Object)
Dim thisButton As Button = sender
Dim thisWhereas As Whereas = thisButton.Parent.Parent
phWhereas.Controls.Remove(thisWhereas)
ControlsList.Remove(thisWhereas.ID)
End Sub
...
Whereas.ascx.vb
Public Delegate Sub ActionClick(ByVal sender As Object)
Public Class Whereas
Inherits System.Web.UI.UserControl
...
Public Event OnRemoveWhereasClick As ActionClick
Public Sub btnRemoveWhereas_Click(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent OnRemvoeWhereasClick(sender)
End Sub
End Class
After disabling the UpdatePanel (thanks to Yellowfog for the suggestion), I found that the following was happening:
The solution was to generate the IDs of the dynamically-added user controls using GUIDs instead of integers based on the number of controls in the list. This way they are essentially guaranteed to be unique.