Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dynamically Loaded Controls: Easy

0.00/5 (No votes)
20 Jul 2009 1  
Non bloated way to reload dynamically loaded controls with eventing intact

Introduction

When using dynamically loaded controls (by using .loadcontrol() method), there are multiple things to consider, especially the following three problems must be solved.

  1. Control must not disappear after postback (first problem)
  2. Content of the control must be preserved (second problem)
  3. Events inside the control must still fire (third problem)

Point 3 being of biggest interest in here. For example, if you would re-load your controls during the Page_Load event, events inside your controls would not fire. (If you re-load them during Page_Init, it is much harder to keep track of what must be loaded, as you might think at first.)

Here is a straightforward way to achieve this.

Background

Dynamically loaded controls are loaded in the codebehind file by a piece of code like this:

 Sub myButton_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles myButton.Click

     tempcontrol = LoadControl("mycontrol.ascx")
     tempcontrol.ID = tmpName
     pContainer.Controls.Add(tempcontrol)
 End Sub

If you are completely new to this, you may read another article in parallel.

Solving the First Problem

The control may look like this:

<%@ Control Language="VB" Inherits="mycontrol"  %>
<asp:textbox id="myText" runat="server" ></asp:textbox>

After clicking mybutton mycontrol will appear on the page because the click event added it. But on the next postback it would vanish, because no one added it. So let's add it :

 Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) _
	Handles mybase.Init      
     if Do_I_have_to_Load(tmpName) then
         tempcontrol = LoadControl("mycontrol.ascx")
         tempcontrol.ID = tmpName
         pContainer.Controls.Add(tempcontrol)
     End if

End Sub

I will explain later about how to get Do_I_have_to_Load and tmpName.

Solving the Second Problem

This one is short: There is one line in the code above:

 tempcontrol.ID = tmpName

All you have to do is, always give the same ID to the same control. Then Viewstate and Postback data will be preserved. (This is easy and is mentioned in a lot of other articles.)

Solving the Third Problem

This is the core of this article, although it is already solved in the above code, when I mentioned to use the INIT event for reloading controls, that will wire up all the events inside your user control. (I'm speaking of events not dynamically added, as these must be re added by code, anyway.)

So the final question is how does Do_I_have_to_Load(tmpName) work?

There are plenty of suggestions around in the net, some suggest to remember dynamic controls in Viewstate after the Button click. But during the Init Event:

  • viewstate is empty
  • all controls (like hidden Textbox) are in their initial state (e.g. empty)

So forget about this. The next idea is to use session, but:

  • session can expire
  • how to handle multiple windows with on sessionvariable...
  • session is a lot of overhead

So forget about that, too.

To get a solution, I just looked at what is accessible during Page_Init ... answer postbackdata:

 Function   Do_I_have_to_Load(tmpName as String) as Boolean
            If Not Request.Params( tmpName & "$myText") Is Nothing Then
                return True
            ElseIf Not Request.Params( tmpName & ":myText") Is Nothing Then
                return True
            ElseIf Not Request.Params( tmpName & "_myText") Is Nothing Then
                return True
            End If
            return false
 End Function

As you see, this solution uses the Request.Param collection to check, if a controlvalue is posted back, that belongs to a dynamic control. (If you found this trick already somewhere on the net, leave a comment, please.) And because .NET changes separator naming convention depending on the .NET version  ( _ or $ or : as separator), I test for all of them.

Limitations

You might find it ugly to lookup a controlname (myText) inside a user control, because you must be sure myText will never be hidden. Consider using Input Type=Hidden for this.

I didn't include a Framework for "remembering" controlIDs and ContainerIDs ... hardcode them or use the mentioned input type=hidden method?

History

  • 20th July, 2009: Initial version; some spellchecking and clarifications

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here