I'm building an ASP.Net web page in which there's a need to display any one of about twenty different user controls at any one time. The contents of each user control is varied, with each holding a different assortment of labels, textboxes, dropdown listboxes, etc. Assorted criteria on the page determines which user control is displayed. The image shown on the left shows a trio of examples representing the [blue] web page and different [orange] user controls.
I don't have a lot of experience with ASP.Net user controls but when I have used them there'd typically be 2 or 3 on every page in the project, representing such things as a toolbar, a pulldown menu, a navigation menu, etc. In those cases it was easy enough to just refer to the user control directly, performing a simple cast like this:
ToolBar toolBar = (ToolBar)...
But the situation with this page is quite different. With it I have a PlaceHolder control called "placeHolderSubForm" into which one user control at a time will be loaded. Where the difficulty arises is when it's time to cast from a Control object to a specific User Control type. For example, if the first user control shown were loaded into the web page then the cast might look like this:
UserControlA ucA = (UserControlA)placeHolderSubForm.Controls[0]
That works okay if there are one or two user controls to deal with but with 20 of them I immediately realized that the code would get rather unwieldy, with a whole lot of switch-case statements necessary to determine which User Control type to cast to. I wanted something much more generic!
At the end of the day the interaction between the web page and each user control is fairly basic, consisting of:
- Passing some basic parameters to each user control.
- Retrieving a varied assortment of user entered data from each user control.
After much research I opted to construct a base class that each user control would be derived from. It's still evolving but here's what it looks like so far:
public class UserControlBase : System.Web.UI.UserControl
{
// Input Parameters (more to be added when required)
public virtual int ContractIdx { get; set; }
// Output Data - passed via SortedList
public SortedList NewData = new SortedList();
// Generic event handler to notify parent web page
public virtual event EventHandler NewData_Handler;
}
In this way, within each user control I can add newly entered data to the general purpose SortedList container 'NewData' via a key & value pair. Thus, one user control might retrieve the following data from a user:
- Width: 5.0
- Height: 7.0
- Length: 144
- Grade: 2.7%
- Overtime: Yes
- Crew: Alpha Prime
Then back in the web page the container can be retrieved like this:
SortedList newData = ((UserControlBase)placeHolderSubForm.Controls[0]).NewData;
Please note that I have posted this blog entry not as "the definitive way" to do this kind of thing but simply to throw out to the ASP.Net developer community what approach I've used. I very much look forward to feedback from others about alternate approaches they prefer and will definitely modify things accordingly if I learn of a better practice.