I have a VB ASP.NET web application with two User Controls each containing one text input. There are two submit buttons each corresponding to one of the User Controls.
Clicking a button adds an instance of its corresponding User Control. For the most part this works except that in a specific scenario the IDs of the textboxes get mixed up thereby mixing up previously entered values.
The problem scenario is as follows:
1) Click the second button (the Add Approver button) twice and enter some values in the two resulting textboxes (for ease of analysis make the values different).
2) Click the first button (the Add Document button) once. (There is no need to add any value in the resulting textbox here.)
At this point everything appears correct. Viewing the page source, I see that the two "Approver" textboxes have IDs of ctl02_txtApprover and ctl03_txtApprover and the one "Document" textbox has an ID of ctl04_txtDocument.
- Click the first button (the Add Document button) again.
At this point the value in the first "Approver" textbox disappears. The value in the second "Approver" textbox migrates to the first "Approver" textbox. Viewing the page source, the IDs for the two "Approver" textboxes have changed to ctl03_txtApprover and ctl04_txtApprover. The migrated values make sense considering that the textbox IDs have changed. In other words, the ViewState appears correct but the control IDs are incorrect.
I have made the code as simple as I can and have posted it here.
Default.aspx
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="WebApplicationUserControlTest._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">
<asp:PlaceHolder ID="phDocument" runat="server" />
<asp:Button ID="btnAddDocument" runat="server" Text="Add Document" />
<br /><br />
<asp:PlaceHolder ID="phApprover" runat="server" />
<asp:Button ID="btnAddApprover" runat="server" Text="Add Approver" />
</form>
</body>
</html>
Default.aspx.vb
Public Class _Default
Inherits System.Web.UI.Page
Private Const VIEWSTATE_DOCUMENT_COUNT As String = "DocumentCount"
Private Const VIEWSTATE_APPROVER_COUNT As String = "ApproverCount"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ViewState(VIEWSTATE_DOCUMENT_COUNT) = 0
ViewState(VIEWSTATE_APPROVER_COUNT) = 0
Else
're-display any preexisting dynamic sections on postback
AddAllDocumentInfoSections()
AddAllApproverSections()
End If
End Sub
Protected Sub btnAddDocument_Click(sender As Object, e As EventArgs) Handles btnAddDocument.Click
ViewState(VIEWSTATE_DOCUMENT_COUNT) += 1
AddDocumentSection()
End Sub
Protected Sub btnAddApprover_Click(sender As Object, e As EventArgs) Handles btnAddApprover.Click
ViewState(VIEWSTATE_APPROVER_COUNT) += 1
AddApproverSection()
End Sub
Private Sub AddAllDocumentInfoSections()
For i As Integer = 0 To ViewState(VIEWSTATE_DOCUMENT_COUNT) - 1
AddDocumentSection()
Next
End Sub
Private Sub AddAllApproverSections()
For i As Integer = 0 To ViewState(VIEWSTATE_APPROVER_COUNT) - 1
AddApproverSection()
Next
End Sub
Private Sub AddDocumentSection()
Dim c As UserControl = LoadControl("~/Document.ascx")
phDocument.Controls.Add(c)
End Sub
Private Sub AddApproverSection()
Dim c As UserControl = LoadControl("~/Approver.ascx")
phApprover.Controls.Add(c)
End Sub
End Class
Document.ascx
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="Document.ascx.vb" Inherits="WebApplicationUserControlTest.Document" %><asp:TextBox ID="txtDocument" runat="server" /><br /><br />
Approver.ascx
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="Approver.ascx.vb" Inherits="WebApplicationUserControlTest.Approver" %><asp:TextBox ID="txtApprover" runat="server" /><br /><br />
I am using Visual Studio 2010. The Target Framework is 4.0. I have tried changing the clientIDMode but this does not seem to make a difference. Have I run into a bug with .NET or is there something wrong with my code?