Click here to Skip to main content
6,628,952 members and growing! (20,647 online)
Email Password   helpLost your password?
Web Development » User Controls » General     Intermediate License: The Code Project Open License (CPOL)

Dynamically add and remove user controls

By Neil Meredith

Dynamically add and remove user controls to a page and maintain the control state.
Javascript, CSS, HTML, XHTML, .NET (.NET 3.5), ASP, ASP.NET, WebForms, Ajax, Dev, Design
Posted:2 Jun 2008
Updated:9 Jun 2008
Views:36,779
Bookmarked:43 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
17 votes for this article.
Popularity: 5.52 Rating: 4.48 out of 5

1
1 vote, 5.9%
2
1 vote, 5.9%
3
4 votes, 23.5%
4
11 votes, 64.7%
5

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

    'Declare the event that we want to raise 
    '(we'll handle this in the parent page)
    Public Event RemoveUserControl As EventHandler


    Protected Friend Sub btnRemove_Click(ByVal sender As Object, _
              ByVal e As System.EventArgs) Handles btnRemove.Click
        'Raise this event so the parent page can handle it
        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()
        'Determine which control fired the postback event. 
        Dim c As Control = GetPostBackControl(Page)

        If Not IsNothing(c) Then
            'If the add button was clicked, increase 
            'the count to let the page know we want
            'to display an additional user control
            If c.ID.ToString = "btnAdd" Then
                ltlCount.Text = Convert.ToInt16(ltlCount.Text) + 1
            End If
        End If

        'Be sure everything in the placeholder control is cleared out
        ph1.Controls.Clear()

        Dim ControlID As Integer = 0

        'Since these are dynamic user controls, re-add them every time the page loads.
        For i As Integer = 0 To (Convert.ToInt16(ltlCount.Text) - 1)
            Dim DynamicUserControl As WebUserControl = _
                  LoadControl("WebUserControl.ascx")

            'If this particular control id has been deleted 
            'from the page, DO NOT use it again. If we do, it will
            'pick up the viewstate data from the old item that 
            'had this control id, instead of generating
            'a completely new control. Instead, increment 
            'the control ID so we're guaranteed to get a "new"
            'control that doesn't have any lingering information in the viewstate.
            While InDeletedList("uc" & ControlID) = True
                ControlID += 1
            End While

            'Note that if the item has not been deleted from the page, 
            'we DO want it to use the same control id
            'as it used before, so it will automatically maintain 
            'the viewstate information of the user control
            'for us.
            DynamicUserControl.ID = "uc" & ControlID

            'Add an event handler to this control to raise 
            'an event when the delete button is clicked
            'on the user control
            AddHandler DynamicUserControl.RemoveUserControl, _
                       AddressOf Me.HandleRemoveUserControl

            'Finally, add the user control to the panel
            ph1.Controls.Add(DynamicUserControl)

            'Increment the control id for the next round through the loop
            ControlID += 1
        Next
    End Sub

    Private Function InDeletedList(ByVal ControlID As String) As Boolean
        'Determine if the passed in user control ID 
        'has been stored in the list of controls that
        'were previously deleted off the page
        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)
        'This handles delete event fired from the user control

        'Get the user control that fired this event, and remove it
        Dim DynamicUserControl As WebUserControl = sender.parent
        ph1.Controls.Remove(sender.parent)

        'Keep a pipe delimited list of which user controls 
        'were removed. This will increase the 
        'viewstate size if the user keeps removing 
        'dynamic controls, but under normal use
        'this is such a small increase in size that it shouldn't be an issue.
        ltlRemoved.Text &= DynamicUserControl.ID & "|"

        'Also, now that we've removed a user control decrement 
        'the count of total user controls on the page
        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
        'Handled in page load
    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
        'Find the specific user control that we added to this 
        'placeholder, and then get the selected values
        'for the dropdownlist, checkbox, and textbox and print them to the screen.
        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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Neil Meredith


Member

Occupation: Software Developer (Senior)
Company: Talbots/JJill
Location: United States United States

Other popular User Controls articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 21 of 21 (Total in Forum: 21) (Refresh)FirstPrevNext
GeneralThanx a lot for the gr8 code PinmemberMember 45688155:10 10 Feb '09  
Questiondynamic user controls inside static user control inside page ? Pinmemberjose.ramirez99912:06 30 Jan '09  
GeneralGreat article! Do you have a c# version of this? PinmemberJayman9118:16 21 Nov '08  
GeneralRe: Great article! Do you have a c# version of this? PinmemberNeil Meredith14:42 23 Nov '08  
GeneralRe: Great article! Do you have a c# version of this? Pinmemberdscoduc12:44 10 Jun '09  
GeneralRe: Great article! Do you have a c# version of this? PinmemberZubair Alam2:20 4 Sep '09  
Questioncode example not downloadable PinmemberMember 46765364:50 18 Nov '08  
AnswerRe: code example not downloadable PinmemberNeil Meredith14:29 23 Nov '08  
GeneralVery Nice Approach Pinmembermanoj_kr7415:07 11 Nov '08  
GeneralThank You PinmemberTroy compton12:22 29 Oct '08  
Generalerror Pinmemberpoombatta0:52 17 Sep '08  
GeneralRe: error PinmemberNeil Meredith2:37 17 Sep '08  
GeneralRe: error Pinmemberpoombatta20:52 17 Sep '08  
GeneralRe: error Pinmemberpoombatta20:54 17 Sep '08  
GeneralRe: error PinmemberNeil Meredith17:26 18 Sep '08  
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·PermaLink3.50/5 (2 votes)
GeneralValidate controls after clicking on "Add" button PinmemberPriyatam K3:04 8 Aug '08  
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·PermaLink4.00/5 (1 vote)
GeneralRe: Validate controls after clicking on "Add" button PinmemberNeilCM14:39 9 Aug '08  
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
GeneralRe: Validate controls after clicking on "Add" button PinmemberPriyatam K0:08 12 Aug '08  
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·PermaLink1.83/5 (4 votes)
QuestionAdd mutilple user controls dynamicly in the page Pinmemberbolboln012:38 27 May '09  
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
AnswerRe: Add mutilple user controls dynamicly in the page PinmemberNeil Meredith18:05 27 May '09  
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
GeneralRe: Add mutilple user controls dynamicly in the page Pinmemberbolboln010:14 28 May '09  
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·PermaLink3.50/5 (2 votes)

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 9 Jun 2008
Editor: Smitha Vijayan
Copyright 2008 by Neil Meredith
Everything else Copyright © CodeProject, 1999-2009
Web10 | Advertise on the Code Project