Practical ASP.NET

User Controls as Objects

ASP.NET developers don't fully exploit User Controls -- until they start thinking of them as "User Interface" objects.

User Controls reveal their true power when you put one on a page and let it interact with the other parts of the page. However, to get your User Controls to interact with the other controls on the page, you need to think of them not as little Web pages but as objects that happen to display a user interface.

Loading User Controls
While you can drop a User Control onto a page at design time, you can also load a user control onto the page at run time just as you would any other object. However, you don't use the New keyword to load a User Control. You use the Page's LoadControl method:

Dim myc As MyControl
myc = CType(Me.LoadControl("MyControl.ascx"), MyControl)

Unlike other objects, since a User Control displays part of your user interface, you need to get your User Control onto the page. The easiest way to do this is to put a Panel on your page and add your control to the Panel's Controls collection:

Me.MyPanel.Controls.Add(myc)

Always add the User Control to the page in the Page's PreInit event. When a user clicks on a submit button in the browser, the data on the page is gathered up and sent back to the server. Back on the server, ASP.NET retrieves the page and recreates all of the design-time controls before the PreInit event fires; after the PreInit event fires, the ASP.NET slots the data that came up from the browser into the appropriate controls on the page. If you haven't added your User Control to the page in the PreInit event, then you won't get the data that comes up from the browser.

Methods, Properties and Events -- Oh, My!
To fully act as an object, though, your control needs to provide an interface that exposes methods, properties and events. Exposing methods is easy: Just declare your subroutines and functions with the Public keyword. Creating Properties is equally easy since each property routine consists of a Get routine (which looks like a function) and a Set routine (which looks like a subroutine).

It's Events that make developers nervous. I had a question from a reader recently who had a User Control with one button on his User Control for each letter of the alphabet. The problem was how to notify the host page for the User Control when each button was clicked. The easiest solution is to have the User Control fire an event that notifies the host page that one of the buttons was pressed and pass the letter represented by the button.

That requires enough of an explanation that I'll have to leave that for my next column. Instead, I'll finish up by looking at a more mundane problem: avoiding writing one event procedure for each button.

When a developer adds a button to a page, typically the next thing the developer does is double-click on the button to create an event handling routine for the button's Click event. It's not necessary to create a separate Click event routine for each Button because you can wire up a single event routine to as many controls as you want.

In C#, you don't even need to write any code to make this happen. First, drag one button onto the page and double-click it to create its Click event routine. After the routine is created, copy the event routine's name (e.g., "MyButton_Click"). Then return to your .ASPX file and drag your second button onto the page. Once the button is on the page, go to the Properties Window for the button, switch to the Event list and paste the name of the first routine into the Click event property for the second button. Repeat this for all of the buttons on the page and all of your buttons will now be calling the same routine.

In Visual Basic, it's actually easier but you have to write some code. Drag all of your buttons onto the page and then double-click on the first one. Once the first event routine is created, go to the end of the event's line where you'll find something like "Handles MyButton.Click." Type a comma and add the name of your second button and its event to give something like this:

...Handles MyButton.Click, MyNextButton.Click

You can keep adding Button Click events to this single routine as long as you separate each Button event name from the previous one with a comma.

Of course, you'll want to know inside the routine which button called it -- but I'll cover that in the next column also.

About the Author

Peter Vogel is a principal in PH&V Information Services, specializing in ASP.NET development with expertise in SOA, XML, database, and user interface design. His most recent book ("rtfm*") is on writing effective user manuals, and his blog on technical writing can be found at rtfmphvis.blogspot.com.

Reader Comments:

Mon, Jun 29, 2009 Sarika Sat Cambodia

Good article. I have 26 buttons from A to Z on a page. Unfortunately,I have one event procedure for each button. If A is clicked, it sends string "a" to a function FilterByLetter. B is clicked, it sends "b" to FilterByLetter function. Same for the rest of the buttons. You said you could wire up a single event routine to as many controls as you want. Like I said above, I'm not sure on how to determine to send different param when each button is clicked.

Tue, Jun 23, 2009 Peter Vogel Canada

Chad: You have at least three choices. If the properties that you want to set are the same on every control then you can have all your user user controls inherit from a base control with those properties. You can then cast all of your user controls to the type of your base control. A similar process would work by having all of your user controls implement the same interface. If, on the other hand, each of your user controls have different properties then you'll have to use Reflection to determine the control's type dynamically at runtime and then retrieve an array of properties that you can set. If you want, send me an e-mail and we can work out the code.

Mon, Jun 22, 2009 Chad http://www.facepalm.com

I have a system on a website that applies user controls to pages that the database tells it to. So I have a content table and a contentUserControl table that basically has contentID and userControlPath in it. So when a page on my site loads, it goes out and finds all the user controls associated with that page and adds them to it. What I want to do is be able to have another table in the database that controls user control properties and sets them according to the data. So I would have another table called something like contentUserControlProperties which would have userControlID and propertyName and propertyValue. As I'm looping through all the user controls for a page and adding them, how do I cast them as the type I need them to be in order to apply a property to them? Here is the loop code I use where I need to cast them into the objects I want in order to add the properties. Private Sub addUserControls(ByVal Above As Boolean) Dim UserControls() As String = Me.UserControls(Above) If Not IsNothing(UserControls) AndAlso UserControls.Length > 0 Then For Each UserControl As String In UserControls Dim uc As Control = LoadControl(UserControl) If Above Then pnlUserControlsAbove.Controls.Add(uc) Else pnlUserControls.Controls.Add(uc) End If Next End If End Sub

Sun, Jun 21, 2009 Joseph Ghassan Lebanon

I guess this is an entry level Tip and shouldn't be classified as an article.

Sun, Jun 21, 2009 Shai Aharoni Israel

Good Article.
The tip about adding User Controls in the PreInit Event is very usuful.

Thanks.

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above