RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Web Control Templates Explained : Page 5

Programming for extensibility assures ease of maintainability in your design. Control templates offer this functionality to custom Web controls.

Designer Editing
With the awesome designer that Visual Studio provides for ASP.NET development, it's almost a shame when you have to transfer to ASPX view in order to accomplish something. This used to be the case with template editing unless you did a tremendous amount of work. This is no longer the case in ASP.NET 2.0 as Microsoft provided an infrastructure for adding designer editing to the control templates.

You do designer editing for control templates inside a control designer class. This partner class provides several overridable methods and properties to add design-time functionality to Web controls. Among these are Smart Tags, Auto-formatting, and of course Template Editing. I cannot cover the intricacies and full power of control designer classes in this article but I will cover some of the basic essentials.

A control designer class inherits from the System.Web.UI.Design.ControlDesigner class. This base class provides many properties and methods to override in order to accomplish what you need. You'll find the ControlDesigner class in the System.Design assembly which is not automatically referenced in a Web control project so you must go out and get it. The designer class is "wired" to a Web control using the Designer attribute on the class declaration.

A Control Designer class provides design-time functionality for a Web control and is wired to the control by way of a class-level attribute decoration.
   Designer(GetType( _
In this example, the EmailContactDesigner class is my designer class which inherits from the framework's ControlDesigner class.

In order to add template editing capability to a control you'll override the Initialize method of the designer class and set a flag that informs the designer that we're going to support template editing.

   Public Overrides Sub Initialize( _
      ByVal Component As IComponent)
      SetViewFlags(ViewFlags.TemplateEditing, True)
   End Sub
Notice the call to the base method to make sure I didn't cancel anything I wasn't supposed to. Wouldn't it be great if that was all there was to it? Well, unfortunately I'm not that lucky, however the code I'm going to write next allows easy categorization of templates so the page developer has a friendly interface with which to work.

The design Microsoft put in place lets you categorize templates into template groups, in the case that you have many templates in your control. The template itself is defined in an object called TemplateDefinition and a TemplateGroup object contains one or more of these definition objects. TemplateGroup objects are themselves contained in an object of type TemplateGroupCollection, so it is here that you declare a variable of that type at the class level in your designer class.

   Private o_TemplateGroups As _
      TemplateGroupCollection = Nothing
This collection gets built in a property called TemplateGroups which I now have to override. It is the contents of this property that will be exposed to the page developer for template editing.

   Public Overrides ReadOnly Property _
      TemplateGroups() As TemplateGroupCollection
         If o_TemplateGroups Is Nothing Then
         End If
         Return o_TemplateGroups
      End Get
   End Property
In this property override, I'm going to build the TemplateGroupCollection that Visual Studio will use. The infrastructure will cache the TemplateGroupCollection object which is why it is declared at a class level. The "is nothing" check in the property prevents the unnecessary rebuilding of this object.

First I'll initialize the o_TemplateGroups object by setting it to the TemplateGroups property of the base class. This not only instantiates it for me but following this technique, I establish a code architecture for a possible future inheritance chain in control designer classes.

   o_TemplateGroups = MyBase.TemplateGroups
The next thing I need to do is identify the actual control you're "designing." In a control designer class that is wired to a Web control, the actual instance of the control being designed is obtainable in the Component variable that is defined in the base class. Many of the method and property overrides in a designer class make use of the actual control being designed, including the TemplateGroups property. So standard procedure is to declare an object variable and cast it to the Web control's type.

   Dim ctl As EmailContact = _
      CType(Component, EmailContact)
I'll use this variable in a few minutes, but first I have to set up the two object variables I want to use for TemplateGroup and TemplateDefinition objects.

   Dim o_TemplateGroup As TemplateGroup
   Dim o_TemplateDefinition As TemplateDefinition
Now I can define groups and templates. Creating a new template group requires very complicated code so pay close attention here.

   o_TemplateGroup = New TemplateGroup( _
      "Surrounding Templates")
I know, I know, I'm a smart-aleck. The text "Surrounding Templates" will appear as the category heading for whatever template definitions I place in this group.

   o_TemplateDefinition = New TemplateDefinition(Me, _
      "Header Template", ctl, "HeaderTemplate", False)
Let's go over the arguments in the TemplateDefinition constructor. The first is the instance of the designer incorporating template editing, usually just Me. The second argument is the name of template as it will be displayed in a context menu or a smart tag. Then you have the control you're designing; remember you obtained this earlier by casting the Component object. The next argument is the name of the template property in the control. The Boolean argument that trails it off is set to False so this template will accept both server controls and HTML controls. Setting it to True will allow only the addition of server controls (regular Web controls) to the template.

As you can guess, you must repeat this for every template and every template group you want to define. The end result is my o_TemplateGroups object nicely filled with all my template definition information and that is what I return in this property. Listing 1 shows the full property code.

Figure 3: The EmailContact control in Template-editing mode.
With the designer code done, let me show you the results. If I recompile my control and site, I can now right-click on it and I'll see "Edit Template" added to the context menu. The listing in the submenu will display the template groups I defined in the designer class. And when I select the "Surrounding Templates" group, I'll see something like Figure 3. You can see the controls that I manually added to the two templates and in fact I can now drag other controls directly from the toolbox. I can right-click again and select "End Template Editing" to return back to the standard control view and display the template contents in the control.

An "Edit Templates" link has also automatically been added to the control's smart tag. If a smart tag did not exist previously, then one was automatically created for me when I added the template editing code to the designer class. Smart tags are another new 2.0 feature and I'll write about them in a future article.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date