I've noticed that I get quite a bit of traffic on my blog for my "Custom Controls Everywhere" posts.  This page in particular has driven a bunch of people to Custom Controls Everywhere and ASP.NET MVC, Part 0.  The response to the link is actually consistent with a question I've gotten a couple of times in email and in person too.  In fact, it's also the gut reaction whenever I tell someone to use custom controls everywhere--something alluding to it costing too much.

I think what I've failed to lay out with my custom controls everywhere sermon is that it's cheap.  Heck, it's almost free.  With VS 2008's Intellisense support, it's really dang easy.

Whenever I create a new ASP.NET (WebForms) application, or a WinForms application, the first thing I do, before writing any app code, is create a new Page/Form base class, and then custom controls for Textbox, DropDownList/ComboBox, Checkbox, RadioButton, Button, etc., whatever I know I'm going to use.

Here's some example code for this:

   1: using System;
   3: namespace CustomControlsEverywhere
   4: {
   5:     public class Page : System.Web.UI.Page
   6:     {
   7:     }
   8: }
   1: using System;
   3: namespace CustomControlsEverywhere.Controls
   4: {
   5:     public class TextBox : System.Web.UI.WebControls.TextBox
   6:     {
   7:         public new CustomControlsEverywhere.Page Page
   8:         {
   9:             get
  10:             {
  11:                 return base.Page as CustomControlsEverywhere.Page;
  12:             }
  13:         }
  14:     }
  15: }

With that, I have a custom Page base class and a custom TextBox.  Repeat the TextBox code for all controls expected to be used, and you have created "Custom Controls Everywhere."

Using the custom page base class and the custom textbox is easy too.  Here's how to make your Default.aspx use your own Page base class:

   1: public partial class _Default : CustomControlsEverywhere.Page

Then in order to use your TextBox, the ASPX markup looks like this:

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CustomControlsEverywhere._Default" %>
   2: <%@ Register TagPrefix="Controls" Namespace="CustomControlsEverywhere.Controls" Assembly="CustomControlsEverywhere" %>
   4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   6: <html xmlns="http://www.w3.org/1999/xhtml" >
   7: <head runat="server">
   8:     <title></title>
   9: </head>
  10: <body>
  11:     <form id="form1" runat="server">
  12:     <div>
  13:         <Controls:TextBox runat="server" />
  14:     </div>
  15:     </form>
  16: </body>
  17: </html>

The important line is the <%@ Register ... %> where we register the "Controls" namespace.  Feel free to make this whatever you want, I just used Controls for illustration.

CustomControlsEverywhere-IntellisenseInASPX What's great is that after you build your solution, and wait a few seconds for Intellisense to catch up, you get the same help with your custom controls that you get with the stock controls.

One of the common pitfalls is namespace collisions.  If you stick with TextBox, DropDownList, Button, etc. for your custom control names, you'll run into collisions within your code-behind.  But since your control has the stock control as its base class, this often doesn't matter--it only comes into play when you try to access a new property or method on your control that the stock control doesn't have.  But this situation is very manageable and it doesn't take long to get used to it.

As you can see, when you're creating a new project, it is very easy and cheap to create custom controls everywhere.  Where it does get difficult and expensive is when you have hundreds of existing screens referencing stock controls and you need to implement a custom control.  And that is exactly why I preach "Custom Controls Everywhere" in the first place--if you start off this way, you won't regret it, but if you start with the stock controls, you very well might regret that.