Customize Custom Controls

Put the finishing touches on a custom control to make it more professional.

asp.netNOW Q&A

LANGUAGES: C# | VB .NET

TECHNOLOGIES: Custom Controls

 

Customize Custom Controls

Put the finishing touches on a custom control to make it more professional.

 

By Josef Finsel

 

In the previous installment of this column (User Controls or Custom Controls), we explored the differences between creating a user control and a custom control, and we created a rudimentary custom control to display page counts based on a Web service. This week, 'let's improve on that control and give it the functionality you'd expect - from having a unique icon to modifying the control at design time to reflecting the property box settings.

 

Add an Icon

If you walked through the code in the previous installment of this column, you probably noticed the icon that showed up when you added the control to the toolbox is the ubiquitous pair of gears Microsoft defaults to for controls and such. Now, you might like something a little snazzier, so we're going to create a custom icon. This is really simple. Open the project that contains the custom control (you can download the code for this article) and add a new item, a bitmap, giving it the same name as the control, rdbaPageCounter.

 

This opens a window in Visual Studio .NET containing a 48 x 48 pixel bitmap. Click anywhere inside the bitmap so you can edit the properties. It needs to be 16 x 16 pixels for the icon, and 16 colors is best. I made a simple and garishly colored icon for testing purposes. Once you've finished your masterpiece, save it and build the control. If you've added this control to your toolbox already, delete it by left-clicking on it and selecting Delete from the pop-up menu. Now add it to the toolbar the same way you did last week and you should see your icon instead of the gears.

 

Build Design-Time Smarts

Now you get to the coolest part - modifying your design time to reflect, in real time, the changes you make in the tool's property. To understand how this works, take a look at object orientation. Your control inherits from System.Web.UI.WebControls.Label. This means everything a Label has, your control has, and you can add things to it.

 

If you don't provide a method specifically, the control you're inheriting from takes care of it. In this case, you're going to override GetDesignTimeHtml. This is the method VS .NET calls when it displays the control during design time. For more information on .NET and objects, read Markus Egger's excellent article Object-oriented ASP.NET Programming.

 

The design-time part of the control isn't actually a part of the Label object but instead a separate part of the framework. This means the first step is to add a reference to System.Web.UI.Design to your project using Project | Add Reference. This should show up in the .NET list. Now you need to add an additional class to handle the code to your rdbaPageControl project, PageControlDesigner. You need to have all the namespace assemblies from your control referenced here as well as System.Web.UI.Designer (see Figure 1).

 

using System;

using System.IO;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.Design;

namespace PageCounterWebControl_CS

{

   public class PageControlDesigner :

    System.Web.UI.Design.ControlDesigner

   {

      public override string GetDesignTimeHtml()

      {

         rdbaPageCounter ctl = (rdbaPageCounter ) Component;

         StringWriter sw = new StringWriter();

         HtmlTextWriter output = new HtmlTextWriter(sw);

         System.Web.UI.WebControls.Label lbl =

          new System.Web.UI.WebControls.Label();

         lbl.BorderStyle = ctl.BorderStyle;

         lbl.BorderColor=ctl.BorderColor;

         lbl.BorderWidth=ctl.BorderWidth;

         lbl.Font.Bold = ctl.Font.Bold;

         lbl.Font.Italic = ctl.Font.Italic;

         lbl.Font.Name=ctl.Font.Name;

         lbl.Font.Size = ctl.Font.Size;

         lbl.Font.Underline=ctl.Font.Underline;

         lbl.BackColor=ctl.BackColor;

         lbl.ForeColor=ctl.ForeColor;

         lbl.Height=ctl.Height;

         lbl.Width=ctl.Width;

         lbl.Text = "Page Counter Control<br>" +

           "pagecounter.reluctantdba.com";

         lbl.RenderControl(output);

         return sw.ToString();

      }

   }

}

Figure 1. This code adds design-time support to your application.

 

Now that you have the namespace assemblies, you need to tie everything together by defining this as part of the PageCounterWebControl_CS namespace. Finally, you can get down to coding. Just as you did with your control, define your class as inheriting, this time from System.Web.UI.Design.ControlDesigner. Next, override the GetDesignTimeHTML method with your own code. This is almost the same code you use in the control (which is much cleaner than what was in the original version). The first difference is you need to define a copy of the control to use, named ctl. You'll use this object to get all the formatting properties in the control by referencing this keyword.

 

In addition, the design time doesn't have an HtmlTextWriter, so create a StringWriter and an HtmlTextWriter. In the sample app, because the control isn't really hosted on a page, I simply put a static piece of text up where the page counter text normally would be. Finally, create a new Label object, which is what the control inherits, and use it for rendering your output.

 

To see it in action, rebuild the project and go to the WebForm1.aspx you're using to host a test version of this control. As you make changes you'll notice that absolutely nothing happens. This is because your control doesn't know you've created a Design Time version for it. You need to modify the directive in the control to inform it of the designer:

 

[Designer("PageCounterWebControl_CS.PageControlDesigner,

   PageCounterWebControl_CS"), DefaultProperty("AccountID"),

   ToolboxData("<{0}:rdbaPageCounter runat=server>

   </{0}:rdbaPageCounter>")]

 

The important piece here is the Designer. You provide the qualified name of the class and the name of the namespace. Now rebuild your project and go into the properties of the page counter and watch as it modifies in the design time in response to your changes.

 

Finishing Up: Installation

Now you're almost ready to use this component on a real site, rather than on your development box. The key is that the DLL you've created needs to be copied to the server. This is as simple as connecting to a Web server in VS .NET and dragging a copy of the DLL from your machine to a directory on the server. Everyone who is going to be using your component needs to have a copy on their computer and they can add it to their toolbar.

 

And that's all there is to it. Now you can see how easy it is to create a custom Web control that can look good and make it easier for programmers to use and for teams to have a consistent look and feel.

 

Keep your ASP.NET questions coming! E-mail me at [email protected].

 

The code referenced in this article is available for download.

 

Josef Finsel is a software consultant for a global consulting company and specializes in .NET and SQL Server. He has published a number of VB, .NET, and SQL Server articles, and when he isn't hanging around the aspnetpro forums you can find him working on the syntax for FizzBin.NET, a programming language that works the way programmers have always suspected. He's also author of The Handbook for Reluctant Database Administrators (Apress).

 

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish