Wednesday, December 8, 2010

User Control City

I recently worked on an application that made extensive use of user controls to manage the its user interface. The application was essentially a long wizard, and each step of the wizard collected information through one or more user controls.

Demo1

The design came about due to a business requirement that required extreme flexibility: the customer needed the ability to quickly change the design of any input area on any page, and wanted to be able to change the page on which the input area appeared. The development team was effectively building a live application in prototype mode.

Although each user control was fairly self-sufficient and could operate independently of the others for the most part, we obviously needed an orchestration framework that handled page sequencing, validation, and other housekeeping activities.

For example, the wizard's Previous and Next navigation buttons were handled by a user control that needed to trigger validation in the current page's user controls and handle the results of that validation. We chose to handle that requirement and similar requirements by adding events to the user controls.

The problem with the user control events is that many of them needed to send data to the attached event handlers and receive data from them as well. That requirement couldn't be handled with the standard EventArgs and EventHandler classes built into the .NET Framework.

Although we could have created custom delegates for the events, those delegates would require extra logic to wire up and would not behave like "normal" control events. For example, there'd be no way to wire up a handler through the control declaration in the hosting page.

A little research into event handling yielded the solution to our problem: we needed to use the EventHandler<TEventArgs> generic. This class is also built-in to the .NET Framework, and it is specifically designed to solve the problem we faced. Using the EventHandler generic, you can create a custom EventArgs class and pass variables back and forth between the class raising the event and the class handling the event. Eureka!

I've since used the technique in other projects as well, and every time I do so, I have to look up how it works and refer to previously-written code. Such is the non-intuitive nature of delegates.

I decided that such a useful technique should be better documented, so I put together an article on my NerdyMusings.com site that explains the steps for adding an event with custom event arguments to a user control:

How to Add Events with Custom Arguments to ASP.NET User Controls

I hope the article saves other developers who needs custom event arguments from having to piece together the solution for themselves.