Introduction
I often find myself in a situation where I have a user input form that I want to reuse, but I don't know how many times I'll be reusing it. For example, let's say you want to let users on your site upload images, but you don't know how many images they'll want to upload. Giving the user an "Add" button can let them dynamically add as many upload boxes to the page as they want.
That's fine if you have a single control that you want to add dynamically, but what if you have several controls in a complex layout? In that case, the easiest way to handle this is by wrapping the controls you want to add into a single user control, and then dynamically adding the user control to your page. I'll show you how to do that, how to remove user controls, and also how to access the values of the controls within the user control.
Using the code
First, let's create a user control and populate it with several controls for our "template". The user control content looks like this:
<table>
<tr>
<td>Textbox Example:</td>
<td>
<asp:TextBox ID="tbx1" runat="server" />
</td>
</tr>
<tr>
<td>Dropdown Example:</td>
<td>
<asp:DropDownList ID="ddl1" runat="server">
<asp:ListItem Text="Dropdown 1" />
<asp:ListItem Text="Dropdown 2" />
<asp:ListItem Text="Dropdown 3" />
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Checkbox Example:</td>
<td>
<asp:CheckBoxList ID="cbx1" runat="server">
<asp:ListItem Text="Checkbox 1" />
<asp:ListItem Text="Checkbox 2" />
<asp:ListItem Text="Checkbox 3" />
</asp:CheckBoxList>
</td>
</tr>
</table>
<asp:Button ID="btnRemove" runat="server" Text="Remove" />
<hr />
Now, add an event handler to the code-behind on the user control so we can tell when the Delete button was clicked:
Partial Class WebUserControl
Inherits System.Web.UI.UserControl
Public Event RemoveUserControl As EventHandler
Protected Friend Sub btnRemove_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles btnRemove.Click
RaiseEvent RemoveUserControl(sender, e)
End Sub
End Class
Now that we have the controls we want to display, we'll add the user control to another page dynamically.
There are three important things we have to do in the page load. First, we need to determine what control fired the postback. We need to make sure the "Add" button was clicked.
This needs to be done in the page load event, instead of in the onclick event for the "Add" button, because of the way the ASP.NET page lifecycle works. If we try to add any controls in the onclick event for the Add button (instead of the page load), those values will be blown away when the page posts back.
If the "Add" button was clicked, the next thing to do is increment the count of the user controls to add to the page, so we know how many controls to display. I store this value in a Literal control across postbacks.
We also need to attach an event handler to take care of the 'Delete' button on the user control when it gets clicked. This will remove the control from the Panel and decrement the number of controls on the page.
Finally, once all the setup is taken care of, we can dynamically load all the requested user controls into a PlaceHolder control.
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
AddAndRemoveDynamicControls()
End Sub
Private Sub AddAndRemoveDynamicControls()
Dim c As Control = GetPostBackControl(Page)
If Not IsNothing(c) Then
If c.ID.ToString = "btnAdd" Then
ltlCount.Text = Convert.ToInt16(ltlCount.Text) + 1
End If
End If
ph1.Controls.Clear()
Dim ControlID As Integer = 0
For i As Integer = 0 To (Convert.ToInt16(ltlCount.Text) - 1)
Dim DynamicUserControl As WebUserControl = _
LoadControl("WebUserControl.ascx")
While InDeletedList("uc" & ControlID) = True
ControlID += 1
End While
DynamicUserControl.ID = "uc" & ControlID
AddHandler DynamicUserControl.RemoveUserControl, _
AddressOf Me.HandleRemoveUserControl
ph1.Controls.Add(DynamicUserControl)
ControlID += 1
Next
End Sub
Private Function InDeletedList(ByVal ControlID As String) As Boolean
Dim DeletedList() As String = ltlRemoved.Text.Split("|")
For i As Integer = 0 To DeletedList.GetLength(0) - 1
If ControlID.ToLower = DeletedList(i).ToLower Then
Return True
End If
Next
Return False
End Function
Sub HandleRemoveUserControl(ByVal sender As Object, ByVal e As EventArgs)
Dim DynamicUserControl As WebUserControl = sender.parent
ph1.Controls.Remove(sender.parent)
ltlRemoved.Text &= DynamicUserControl.ID & "|"
ltlCount.Text = Convert.ToInt16(ltlCount.Text) - 1
End Sub
Protected Sub btnAdd_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles btnAdd.Click
End Sub
There's one more issue here. How do we get at the values stored in the user controls? It's actually fairly straightforward. We loop through all the controls in the PlaceHolder, then look at the name of the control to determine if this is one of the user controls we added to the PlaceHolder.
If it is, we can use FindControl to access the values stored in textboxes, dropdowns, checkboxes, or anything else we added to the user control. Here, I'm getting those values and then writing them out to the screen:
Protected Sub btnDisplayValues_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles btnDisplayValues.Click
ltlValues.Text = ""
For Each c As Control In ph1.Controls
If c.GetType.Name.ToLower = "webusercontrol_ascx" Then
Dim uc As UserControl = CType(c, UserControl)
Dim tbx1 As TextBox = uc.FindControl("tbx1")
Dim ddl1 As DropDownList = uc.FindControl("ddl1")
Dim cbx1 As CheckBoxList = uc.FindControl("cbx1")
Dim sb As New System.Text.StringBuilder
sb.Append("Textbox value: " & tbx1.Text & "<br />")
sb.Append("Dropdown value: " & ddl1.SelectedValue & "<br />")
sb.AppendLine("Checkbox values: ")
For Each li As ListItem In cbx1.Items
If li.Selected = True Then
sb.Append(li.Value & "<br />")
End If
Next
sb.Append("<hr />")
ltlValues.Text &= sb.ToString
End If
Next
End Sub
I hope this has given you another way to think about dynamically adding and removing controls. Enjoy!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 20 of 20 (Total in Forum: 20) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
 |
How would this need to be modified to support handling events which occur inside a user control which is dynamically inserted inside another user control which is statically inserted into a page?
Would the events need to be propagated all the way to the page? Or is it possible to handle them in the static user control?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This is exactly what i'm looking for thank you. I'm having some trouble trying to recreate this in c# though. Seems to be because of the handlers. C# doesn't have a "handles" keyword. Any suggestions - or better yet do you have a C# version of this code?
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
I don't have a c# version. Since c# doesn't have the "handles" keyword, get rid of it and instead manually wire up those events in the oninit function when the page loads.
Here's an article I found with a brief explanation of the difference between the "handles" keyword and manually wiring up the events in c#:
http://forums.asp.net/p/704364/704561.aspx[^]
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Hi there, your example given here is what I was looking for (actually i'd prefer c# code). But in order to convert it to running c# code i'd like to have a look into your codeexample but unfortunatly the linky is broken. Please fix the link.
Thank you in advance.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
The link works fine for me...maybe code project was having a problem? I'd try again and see if it works for you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks for your great approach. I was looking similar functioanlity and it helped me almost 50% of my requirement. It would be better if you provide me its C# version .
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
hi, i was so happy when i see this .. I need almost a similar functionality. So I've implemented the same code .for just a trial but when i run this code in my system i got an erroe..that
Parser Error Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Unknown server tag 'asp:ScriptManager'.
Source Error:
Line 19: <form id="form1" runat="server"> Line 20: <asp: xmlns:asp="#unknown"> Line 21: <asp:scriptmanager id="sm1" runat="server" /> Line 22: <asp:updatepanel id="up1" runat="server"> Line 23:
Source File: /WebSite3/Default.aspx Line: 21
-------------------------------------------------------------------------------- Version Information: Microsoft .NET Framework Version:2.0.50727.42;
why this ?..i am usin g microsoft visual studio.net 2005
expecting ur reply soon
</form>
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I created this project in .NET 3.5. If you are running version 2.0, you have to be sure to setup your project as an ajax enabled web project.
That should be one of the project types you can select when you create a new project. You can then compare that web.config to what you have, and add in the necessary fields. If you don't do this, then the script manager will not be recognized.
Or, if you don't want to mess with the web.config file, you can just remove the script manager and update panel tags from the page. It should still work fine, you'll just get a page postback every time you add a new item.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
i can avoid that erro by adding AJAX controls.. then my problem is that when we add new user controls as our requirement how can save the information in each dynamic added user control into a database .
i explai my problem here...that
i created a user control for adding lines in an invoice form then i want to display these control 3 times when the page is loaded first time..and then add line for each time when we press an add button. after thet i want to save these informations into database. also i have some other informations such as invoice no,clientname,invoice date,discount,grand total fields.. can u help me ..as early as possible?..
i just paste my user control design code
<table runat="server" cellpadding="0" cellspacing="0" width="100%"> | Item Name | Description | Unit cost | Qty | Tax | Price | <asp:dropdownlist id="DropDownList2" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox13" runat="server" textmode="MultiLine" xmlns:asp="#unknown">
| <asp:textbox id="TextBox10" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox7" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList5" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox4" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList3" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox12" runat="server" textmode="MultiLine" xmlns:asp="#unknown">
| <asp:textbox id="TextBox11" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox8" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList6" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox5" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList1" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox1" runat="server" textmode="MultiLine" xmlns:asp="#unknown"> | <asp:textbox id="TextBox2" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox3" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList4" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox6" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> |
|
also i want to load each dropdown list box from the database when the user control load.. i believe u got my problem and u will help me..

|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
i can avoid that erro by adding AJAX controls.. then my problem is that when we add new user controls as our requirement how can save the information in each dynamic added user control into a database .
i explai my problem here...that
i created a user control for adding lines in an invoice form then i want to display these control 3 times when the page is loaded first time..and then add line for each time when we press an add button. after thet i want to save these informations into database. also i have some other informations such as invoice no,clientname,invoice date,discount,grand total fields.. can u help me ..as early as possible?..
i just paste my user control design code
<table runat="server" cellpadding="0" cellspacing="0" width="100%"> | Item Name | Description | Unit cost | Qty | Tax | Price | <asp:dropdownlist id="DropDownList2" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox13" runat="server" textmode="MultiLine" xmlns:asp="#unknown">
| <asp:textbox id="TextBox10" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox7" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList5" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox4" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList3" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox12" runat="server" textmode="MultiLine" xmlns:asp="#unknown">
| <asp:textbox id="TextBox11" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox8" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList6" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox5" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList1" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox1" runat="server" textmode="MultiLine" xmlns:asp="#unknown"> | <asp:textbox id="TextBox2" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> | <asp:textbox id="TextBox3" runat="server" width="64px" xmlns:asp="#unknown"> | <asp:dropdownlist id="DropDownList4" runat="server" xmlns:asp="#unknown"> | <asp:textbox id="TextBox6" runat="server" height="24px" width="64px" xmlns:asp="#unknown"> |
also i want to load each dropdown list box from the database when the user control load.. i believe u got my problem and u will help me..

|
| Sign In·View Thread·PermaLink | |
|
|
 |
|
 |
If you want to save the data to the database, just loop through the dynamically created user controls like the last code snippet in the article demonstrates, and at the end of each loop save the data for that item to the database.
Also, can you remove your sample code? It's completely messing up the page formatting. Thanks.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Hi,
Let me first thank you for the wonderful approach to add/remove user controls dynamically. I need almost a similar functionality. So I've implemented the same code and everything is going fine.
I was stuck at a point where I need to validate controls in dynamically added user control. Suppose, I have a textbox in UC and it is a mandatory field. After clicking on Add, I have to check if the textbox in user control has some value in it. If yes, I can add next user control, if no, I have to stop and show a error message to the user.
I've tried to do this in AddAndRemoveDynamicControls() method, but as the controls get cleared in postback, I'm not able to access controls which were previously added. How can I achieve this functionality ?
Please help me regarding this issue. If I'm not clear, please let me know. Thanks very much in advance.
Priyatam K
|
| Sign In·View Thread·PermaLink | 4.00/5 (1 vote) |
|
|
|
 |
|
 |
Priyatam,
You only have access to the control values before the postback is completed. So, what I would do is on the add event, loop through the existing user controls on the page and find out if any are missing the required values.
If there are some required fields missing, store a variable in the viewstate that lets you know there's a problem. Then on the page load, look at the viewstate and determine if any required fields are missing. If they are, remove the last user control in the placeholder and display an error message to the user. Hope that helps.
Neil
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Neil,
Thanks for the reply and sorry for the late response. I had a long weekend and so couldn't respond.
I will try this approach and let you know if it works.
|
| Sign In·View Thread·PermaLink | 1.83/5 (4 votes) |
|
|
|
 |
|
 |
Hi Neil thanks for this amazing code, I am working on a page that needs heavily the feature of adding and removing dynamically user controls and this code is exactly what I need.
however, your code show the add of a single user control, in my case I need nearly 10 user controls to add and remove from my page.
can you show me please what I have to change in this code to handle multiple user controls?
I am new in VB.net and I don't know very well what I must do
thanks in advance
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You would have to add additional event handlers for the new user controls (to handle removing the controls), and duplicate anything that's maintaining the state of the controls(like ltlCount.Text, which is maintaining the count of the user controls currently on the page). It could get a bit messy. It might be easier to combine as many of the controls as you can into one or two dynamic controls, instead of having 10 on the page.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
thanks for your reply Neil
I am working on a kind of a Resume format and this resume has many fields such as skills, professional experiences, interests,etc
each field of these has to be made as a user control so it can be reusable along the page
I can't thus wrap these controls into one or 2 as you suggested
but I will try your method
thanks once again
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|