I used a similar technique when I needed to create custom grids. As in the case of the data-entry forms, I found that several of the grids in my application served as the entry point into the data-entry forms. This meant the grids were accompanied by other visual elements common to all of them, including a heading, an Add-New link, and a No-Items-to-List message. They also shared certain in-row links including Select, Edit, View, etc.
I created these common elements as a custom Web Control similar to the data-entry form example above. Instead of a placeholder though, I actually included a DataGrid in my custom base Web Control. I added a variety of styling properties and other properties to display the Add-New link and position it in different places relative to the grid.
I had about five custom grids to design and I wrote each of them as a custom Web Control that inherited from the base control. Each derived control created the grid columns it needed and provided the Databind method and it raised an event every time the grid needed rebinding to its data source. Such an event was raised in place of the sorting event and paging event the DataGrid gives you out-of-the-box. This meant I trapped the internal grid's events in my custom Web Control and just exposed my own custom event to the outside, telling the page that a rebind was necessary.
In fact, I found a couple of places where I needed to reuse a couple of the grids, just not in their entirety. So I programmed the building of the columns to be dependent on property settings. This allowed the WebForms that used the custom grid controls to simply turn columns off and on by toggling properties. This, combined with the ability to hide the heading and Add-New link and all the styling I provided, allowed me to reuse these controls throughout the site and make them look completely different from one-another. For example, a home page may have a summary listing of people, while a personnel-editing page may have a grid of people with more columns on it. You can use the same Web Control in both cases, but using its custom properties, you would simply hide most of the columns on the summary version on the home page. You can bind the same business object to both controls, which makes using them very simple.
Gluing Controls Together
Depending on your needs, you can have custom Web Controls in your Web application communicate with each other using events. Thanks to the way events work in .NET, you can actually declare events in one control, then declare public methods that adhere to the event signature in another control. The WebForm that contains both Web Controls can "wire" the event in one control to the method in another, thus effectively gluing the controls together so that behavior in one fires functionality in another with no other code interaction at the form level. The possibilities are endless and are limited only by your creativity.
Pattern All You Want
|Figure 6. Web Control Hierarchy: This Web Control hierarchy demonstrates how you can use an inheritance structure to give your UI development an object-oriented twist. The custom controls start at FormBase and every control adds more and more to what is going to be eventually rendered.|
As you can see, I've illustrated a couple of real-world examples where I've used object-oriented techniques to achieve my UI needs. I used simple examples and showed some containment and one level of inheritance, but you can apply OOP and design patterns to the classes that make up your library of WebControls in whatever fashion you see fit.
Let me give you one quick example of where your Web Control inheritance tree can grow to more than just two levels. Say you have about five data-entry forms in your Web application similar to the one I described above. As in the above example, all the data-entry form Web Controls inherit from a common base control that provides common functionality and visual elements. What if two of these forms also shared some additional visual element and/or functionality that the other three do not? You can place these elements into another Web Control which, like the data-entry controls, inherits from the original base Web Control, but itself acts as a base Web Control for these two data-entry form controls. This allows you to build a hierarchy of visual and functional elements in a class structure where each control provides functionality to all derived controls down the line (see Figure 6).
If you're creating a site that creates Web Controls dynamically, you can even have factories set up to instantiate your controls or even use interfaces to call functionality from your Web Controls. I know I'm speaking pretty abstractly here, but I'm just trying to convey that any design pattern you see fit to apply to your design is possible, even in the UI, since your programs use all-too-familiar classes.
I chose to use the word toolkit for lack of a better term. Using a declarative approach, you can design a site to house most of its functionality in the Web Controls that comprise it, including all interaction with a business tier (or database if you choose to). This lets you use the custom Web Controls in any site that needs a little bit of functionality. This appears to be the case with the ASP.NET forums site located at www.asp.net. If you download the source for this project, you'll see that the designers created the site by gluing a bunch of Web Controls together. Though I can't say for sure, it's my understanding that the new Community Server forums (www.communityserver.org) is developed this way as well. The idea here is that if you're writing a site and you want to include a certain forum posting on one of your pages, you can just use one of the custom Web Controls, set some properties, and you're done. If your Web Controls offer sufficient styling properties, you can visually integrate it into the look and feel of your site with no problems at all.
Even More with Avalon
Ever hear of XAML? Well, I won't make this section an introduction to XAML, but I will tell you that it brings declarative programming even more to the forefront in Avalon (coming with Windows Longhorn). XAML is an XML-like language that lets you declare visual objects using tags and properties. You'll be able to use one code base to drive both Windows and Web applications. For example, you can use a <Textbox> tag to display a Web textbox in a browser or a Windows textbox on a WinForm. By now you should understand that the actual code that draws the appropriate object has not disappeared, it has just been taking out of our realm of responsibility. Concepts like this make me think there's some very exciting stuff coming down the pipeline.
Declarative programming using Web Controls definitely has its advantages in code isolation, reusability, and providing versatile functionality. While I believe this practice and approach to ASP.NET design creates more robust Web applications, I think you should use it as one of the tools in your arsenal as a developer; just like every tool and technique you may have acquired through the years. In every project, you need to weigh the functionality your users desire against the available time and resources; and if you're a consultant, you also have to consider the skills of the team who will take over support of your project after you're long gone. I know that the styles I have demonstrated here are supportable in the long run. I have also been fortunate to work with people that have been eager to learn and explore new and even unorthodox techniques. This may not always be the case and you may find that anything more than top-down programming is beyond the reach of some people. In any case, use judgment when you apply these or any techniques to your development. Most sites I have seen that are written in ASP.NET use a conventional page centric (non-Web Control) approach to design and development, and are written very well. My friend Scott is very quick to remind me that design and coding is a very personal art and I believe he could not be more correct. There are many right ways of achieving a goal and every style and technique you learn along the way contributes to increasing your handy, dandy, roving, programming bag of tricks.