Practical ASP.NET
Dynamically Add Controls at Runtime
There are, at least, six ways to have controls magically appear on a page at runtime. Just don't add it directly to the Page.
Working with ASP.NET in design mode, dragging and dropping controls onto a Page's design surface, it's easy to forget that it's just a convenience. Anything you do graphically in Visual Studio
always generates text in some file somewhere. When you drag a control onto a page some code is generated that instantiates the control and adds it to the page.
To put it another way: you could create your Web application by typing that code into Notepad yourself (in which case, you should call it "Visual Notepad"). This is, in fact, an excellent strategy... if you're paid by the hour.
While it may not make sense from a productivity point of view to use this feature in design time, it can make sense at run time. Sometimes you want to add controls (or user controls) to the page dynamically at runtime and instantiating the controls in your code can make sense.
Before looking at that options, consider your alternatives. For instance, if you're adding or removing controls based on the user's security role, the LoginView is a simpler solution. With the LoginView you just add a template for each security role and put the controls appropriate to that role into the template.
Second, you can put all the controls on the page at design time and set the Visible property on some of them to False. At runtime, when you want these controls to be added to the page, just set their Visible property back to True. If you've got multiple controls to appear at one time or another you can put them inside a Panel and manage the Panel's Visible property.
Do be aware that the Visible property would have been better named the "Exists" property. When a control's Visible property is set to False, no clever CSS tricks are performed: The control simply doesn't generate any HTML. As a result, any JavaScript code that manipulates the control will fail when the control's Visible property is False.
A third solution is to use the ASP.NET 2.0 MultiView control: For each different set of controls that you want to display, put a View control inside the MultiView and add the controls to the View. You can control which View is currently displayed by setting the MultiView control's ActiveViewIndex property to the View you want.
However, for ultimate flexibility, you can create controls in your code and add them to some other control's Controls collection (and, remember, the Page itself is just a really big control). When it comes time to generate the HTML for a page, ASP.NET simply cycles through each control's Controls collection calling each control's Render method, which generates the control's HTML.
So, for instance, to add a new ListBox to a page, you should just need this code:
Dim lst As New ListBox
Me.Controls.Add(lst)
The problem is that, with this code, the control won't appear inside a Form tag and the page will throw an exception. The code you actually need looks a little uglier:
Dim lst As New ListBox
Me.Controls(3).Controls.Add(lst)
This code assumes that you're not using a Master Page. If you're using a Master Page the code is much, much uglier. While the same process will work with Content controls, Content controls don't appear in a Page's IntelliSense list. You'll need to retrieve the Content control you want to add your ListBox to from the Page's Controls collection by position -- and you'll have to drill down through several levels of Controls collections to find it.
It's easier to drop a Panel onto your page and add your control to the Panel:
Dim lst As New ListBox
Me.Panel1.Controls.Add(lst)
This also lets you control where your ListBox will appear by, at design time, putting the Panel where you want it on the page.
But, if you're going to add a control, the odds are that you want to add several controls. Rather than adding those controls individually, you should add a User Control containing all of the controls you want. You don't instantiate a UserControl using the New keyword. Instead, you use the LoadControl method which returns a Control object that you can then add to a Panel:
Dim ct As Control
ct = LoadControl("WebUserControl.ascx")
Me.Panel1.Controls.Add(ct)
What I've been omitting in all of these examples is setting the control's properties before adding it to the Panel (e.g. Text, BackColor). One of the benefits of using a User Control is that you can set the properties on the controls at design time rather than at run time.
There you go: six different ways to dynamically add controls to a page at runtime: Here at Visual Studio Magazine we give you a choice, not an echo.
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.