Using Templates

I l @ ve RuBoard

Within your custom control, it is possible to add support for user -defined templates, such as the ones that you learned about in Chapter 5, "HTML/Web Controls." Again, one of the great things about ASP.NET is that you have as much control over your custom controls as Microsoft has when they build their controls. If you see a feature of an existing control, such as the Repeater, that you'd like to implement in your own custom control, you can!

Templates are all about user interface. They allow your control to define one or more templates that can be customized by the user. Your control then defines when and how these templates are rendered. A common use for templates in the list controls was to have an ItemTemplate and an AlternateItemTemplate , which made it easy for users to define a different look for alternating items in a list. Headers and footers are also common candidates for templating.

We can only provide one simple example of a templated control, but this will give you a taste of what is involved. A more thorough investigation into the details of building templated controls is left as an exercise for the reader.

For this example, we will build on our HelloWorld control once more. We need to create two separate classes, one for the control itself, and another for its template. For a more advanced control with many templates, each additional template would require its own class to be defined.

Templates are only really useful if you have multiple properties or data elements within your custom control. If there is only one string to output, for example, then any formatting required could simply be applied to the control, and there is no need for a template. In order to make a template worthwhile for our HelloWorld example, we will be creating three properties for our control: ToPerson , FromPerson , and Message . This control will then render these properties, with the help of a template if one is provided.

All templated controls should implement the INamingContainer interface covered earlier, to ensure that any child controls created are given unique names . The controls must also include several attributes in their class definition to ensure that they are handled properly by the ASP.NET runtime. The first attribute, ParseChildren , must be applied to the class as a whole, and is used to tell ASP.NET to treat any inner (child) tags within your control's tags as properties of your control. The syntax for this, in C#, looks like the following (specifying the name of the parameter is optional):

 [ParseChildren(true)] //or [ParseChildren(ChildrenAsProperties = true)] 

This attribute should be placed immediately before (typically on the line above) your class definition.

The second attribute that is used is TemplateContainer . This attribute is applied to any template definitions, which are properties of the control of type ITemplate . The TemplateContainer attribute needs to be passed the type of the class that is defined to handle the specific template. For example, in our HelloTemplate example, we use

 [TemplateContainer(typeof(MessageTemplateContainer))] 

The complete source for our templated control is shown in Listing 12.11, below.

Listing 12.11 Templated Hello World Control, (HelloTemplate.cs)
 using System; using System.Web.UI; namespace ASPNETByExample {     [ParseChildren(true)]     public class TemplatedHelloWorld : Control, INamingContainer     {         private ITemplate messageTemplate;         private String toPerson = null;         private String fromPerson = null;         private String message = null;         private Control myTemplateContainer;         protected override void OnDataBinding(EventArgs e)         {             EnsureChildControls();         }          [TemplateContainer(typeof(MessageTemplateContainer))]         public ITemplate MessageTemplate         {             get             {                 return messageTemplate;             }             set             {                 messageTemplate = value;             }         }         public String ToPerson         {             get             {                 return toPerson;             }             set             {                 toPerson = value;             }         }         public String FromPerson         {             get             {                 return fromPerson;             }             set             {                 fromPerson = value;             }         }         public String Message         {             get             {                 return message;             }             set             {                 message = value;             }         }         protected override void CreateChildControls ()         {             if (MessageTemplate != null)             {                 // Use user-defined template for rendering                 myTemplateContainer =                     new MessageTemplateContainer(this);                 MessageTemplate.InstantiateIn(myTemplateContainer);                 Controls.Add(myTemplateContainer);             }             else             {                 // Use the default rendering                 Controls.Add(new LiteralControl("<b>To:</b> " +                     ToPerson + "<br/>"));                 Controls.Add(new LiteralControl("<b>From:</b> " +                     FromPerson + "<br/>"));                 Controls.Add(new LiteralControl("<b>Message:</b><p>" +                     Message + "</p>"));             }         }     }     // Keeps a backpointer to the parent control to access its properties     public class MessageTemplateContainer : Control, INamingContainer     {         private TemplatedHelloWorld parent;         public MessageTemplateContainer(TemplatedHelloWorld parent)         {             this.parent = parent;         }         public String ToPerson         {             get             {                 return parent.ToPerson;             }         }         public String FromPerson         {             get             {                 return parent.FromPerson;             }         }         public String Message         {             get             {                 return parent.Message;             }         }     } } 

Let's go over this code ”it's more complicated than anything we've done so far. First we define our class, deriving from Control as usual and implementing INamingContainer . Next we declare our instance variables , which we'll use later. The first method we come to is OnDataBinding() . It is a good practice to always override this method and call EnsureChildControls() so that if any of the controls within a template utilize databinding, we are assured that the controls have been created before ASP.NET attempts to bind them to their data source(s).

We then define our properties, which include an ITemplate called MessageTemplate , which includes the TemplateContainer attribute. This property is used to provide a reference to the MessageTemplateContainer class, so that it can be invoked to handle the contents of a MessageTemplate template. Then we declare our three string properties: ToPerson , FromPerson , and Message .

The last method in the TemplatedHelloWorld class is the CreateChildControls() method, which defines the behavior of our control based on the existence of a template. If a template is supplied, then an instance of MessageTemplate will exist, and we will use the user-defined template to render our properties. Otherwise, the default behavior for this class is to output its properties in three LiteralControls .

The MessageTemplateContainer class is created with a reference to the TemplatedHelloWorld class passed into its constructor, which it sets to the local parent variable. This control can then access TemplatedHelloWorld's properties through this reference, as it does in each of its properties. No rendering logic is required in this control, as it will render its contents automatically using the Control objects Render() method. Its properties are accessed within the template by using the Container.PropertyName syntax with <%# %> tags, as we shall see in Listing 12.12, which shows the source for an ASP.NET page that tests this control.

Listing 12.12 HelloTemplate.aspx
 <%@ Register TagPrefix="Custom" Namespace="ASPNETByExample" Assembly = "HelloWorld" %> <HTML>     <body>         <form runat="server" ID="Form1">             Using Template:             <br />             <Custom:TemplatedHelloWorld                 id="hello1"                 ToPerson="World"                 FromPerson="Steve"                 Message="Hello!"                 runat="server">                 <MessageTemplate>                     <table bgcolor="#CCCCCC">                     <tr bgcolor="#9999FF">                         <th>TO</th>                         <th>FROM</th>                         <th>MESSAGE</th>                     </tr>                     <tr bgcolor="#EEEEEE">                         <td>                             <%# Container.ToPerson %>                         </td>                         <td>                             <%# Container.FromPerson %>                         </td>                         <td>                             <%# Container.Message %>                         </td>                     </tr>                     </table>                 </MessageTemplate>             </Custom:TemplatedHelloWorld>             <hr />             Default (no template):             <br />             <Custom:TemplatedHelloWorld                 id="hello2"                 ToPerson="World"                 FromPerson="Steve"                 Message="Hello!"                 runat="server" />         </form>     </body> </HTML> 

This page includes two instances of our TemplatedHelloWorld control, one with and one without a template. The first instance uses a template to output the contents of the control as cells in a row of an HTML table. The second instance simply outputs the contents of the control using the default rendering defined in the control. Note that in both cases, we are setting the parameters on the control. The results of viewing this page in a browser can be seen in Figure 12.3.

Figure 12.3. Working with templated custom controls.

I l @ ve RuBoard


Asp. Net. By Example
ASP.NET by Example
ISBN: 0789725622
EAN: 2147483647
Year: 2001
Pages: 154

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net