Reusing and Creating Server Controls
page 2 of 4
by Justin Lovell
Feedback
Average Rating: 
Views (Total / Last 10 Days): 24403/ 84

Creating Controls from Scratch
I will start off by discussing about how to create server controls from scratch. There is two classes that you can inherit from – the Control class and the WebControl class. The Control class has no features what-so-ever – it is the essential class that is relied on by the entire user interface in an ASP.NET page.

In a WebControl class, there is additional properties and methods – most of them are protected so the inheriting class can modify the behaviour. The WebControl class is mainly built for rendering HTML a lot easier. Answer the following question below to decide if you should inherit from the WebControl class:

Is the server control going to render one big HTML container to hold all rendering in?

If you answered yes to the question, then inheriting from the WebControl class will be a better option for you to pursue. In my opinion, it is a lot easier to control the WebControl class because the rendering is broken into smaller, logical blocks.

On top of that, it also adds diversity for the page developer to add some attributes during the page life cycle (without you, as the control developer, to add extra code into your control). For example, he might want to add an OnClick attribute to your server control which renders a <table> tag so that the page developer can do his own click event (server-side or client-side – let it be his choice).

To demonstrate the simplicity that the WebControl class can have over the Control class, we will build a simple Label control (without using the built-in controls). The functionality that our Label control must achieve is:

  • Must be able to output text from its Text property or from the control's inline content.

  • The output must be enclosed in the <span> tag.

  • Must have the ability to be classed for formatting from CSS.

For the demonstration to be as simple as possible (and not to overcrowd the code), we will not persist objects to view state. First, we are going to demonstrate with the Control class:

// [C#]
[ToolboxData("<{0}:CustomLabel runat=server></{0}:CustomLabel>")]
public class CustomLabel : Control {
   private string pClassName;
   private string pText = String.Empty;
   public string ClassName {
      get { return pClassName; }
      set { pClassName = value; }
   }
   public string Text {
      get { return pText; }
      set { pText = value; }
   }
   protected override void OnInit(EventArgs e) {
      if ((Controls.Count > 0) && (Controls[0] is LiteralControl))
         Text = ((LiteralControl)Controls[0]).Text;
      base.OnInit (e);
   }
   protected override void Render(HtmlTextWriter writer) {
      writer.RenderBeginTag(HtmlTextWriterTag.Span);
      if (ClassName != null)
         writer.AddAttribute(HtmlTextWriterAttribute.Class, ClassName);
      writer.Write(Text);
      writer.RenderEndTag();
   }
}
' [VB.NET]
<ToolboxData("<{0}:CustomLabel runat=server></{0}:CustomLabel>")> _
Public Class CustomLabel
Inherits Control
   Private pClassName As String
Private pText As String = [String].Empty
   Public Property ClassName() As String
Get
Return pClassName
End Get
Set (value As String)
pClassName = value
End Set
End Property
   Public Property [Text]() As String
Get
Return pText
End Get
Set (value As String)
pText = value
End Set
End Property
   Protected Overrides Sub OnInit(e As EventArgs)
If Controls.Count > 0 AndAlso TypeOf Controls(0) Is LiteralControl Then
[Text] = CType(Controls(0), LiteralControl).Text
End If
      MyBase.OnInit(e)
End Sub
    Protected Overrides Sub Render(writer As HtmlTextWriter)
writer.RenderBeginTag(HtmlTextWriterTag.Span)
       If Not (ClassName Is Nothing) Then
writer.AddAttribute(HtmlTextWriterAttribute.Class, ClassName)
End If
       writer.Write([Text])
writer.RenderEndTag()
End Sub
End Class

Now, we will look at the demonstration with our custom label inheriting from the WebControl class:

// [C#]
[ParseChildren(false)]
[PersistChildren(false)]
[ToolboxData("<{0}:CustomLabel runat=server></{0}:CustomLabel>")]
public class CustomLabel : WebControl {
private string pText = String.Empty;
   public string Text {
get { return pText; }
set { pText = value; }
}
   protected override HtmlTextWriterTag TagKey {
get { return HtmlTextWriterTag.Span; }
}
   protected override void OnInit(EventArgs e) {
if ((Controls.Count > 0) && (Controls[0] is LiteralControl))
Text = ((LiteralControl)Controls[0]).Text;
      base.OnInit (e);
}
   protected override void RenderContents(HtmlTextWriter writer) {
writer.Write(Text);
}
}
' [VB.NET]
<ParseChildren(False), PersistChildren(False)> _
<ToolboxData("<{0}:CustomLabel runat=server></{0}:CustomLabel>")> _
Public Class CustomLabel
Inherits WebControl
   Private pText As String = [String].Empty
   Public Property [Text]() As String
Get
Return pText
End Get
Set (value As String)
pText = value
End Set
End Property
   Protected Overrides ReadOnly Property TagKey() As HtmlTextWriterTag
Get
Return HtmlTextWriterTag.Span
End Get
End Property
   Protected Overrides Sub OnInit(e As EventArgs)
If Controls.Count > 0 AndAlso TypeOf Controls(0) Is LiteralControl Then
[Text] = CType(Controls(0), LiteralControl).Text
End If
      MyBase.OnInit(e)
End Sub
   Protected Overrides Sub RenderContents(writer As HtmlTextWriter)
writer.Write([Text])
End Sub
End Class

Both controls pass on the same minimal functionality; however, only one of them can walk away with an “A” to their name. That “A” will be awarded to the one that inherits from the WebControl class. For the following reason – it is able to be extended very easily by both a page developer and a control developer. Some bright control developer might want to make the tag that contains the text output to be a <div> instead of a <span> tag. Some page developer might want to add some CSS style for the label's style.

For our label control that inherits from the Control class to have that same functionality as the label control that inherits from the WebControl class, a ton of additional lines needs to be added. Another consideration when deciding which one to pursue, also think of making the lives of other control developers (including yourself) to be made easier – read further into the article to learn more about it.


View Entire Article

User Comments

Title: AddAttribute/RenderBeginTag sequence   
Name: Kevmeister
Date: 2005-12-08 8:50:14 PM
Comment:
Shouldn't the AddAttribute calls be executed *before* the RenderBeginTag?
Title: Sockets   
Name: Madhusudan
Date: 2004-09-08 8:37:47 AM
Comment:
Sir,
I need to distribute a control that enacpsulates the socket class. Is it possible to inherit from the socket class and write a custom web control ?
Thanks
Title: Re: composite control   
Name: Justin Lovell
Date: 2004-08-24 1:23:42 PM
Comment:
Senthil,

I have already written an article on the basics of databinding for server controls. You can read this information from here:

http://aspalliance.com/391

And if you want to see how the templates part work out, then you can also read another article that I have written over here:

http://aspalliance.com/366
Title: composite control   
Name: Senthil
Date: 2004-08-24 9:16:32 AM
Comment:
sir
I need to create a user control i want to assign various properties to it ,all the text propeties etc are felt easy to me,but i need to bind the database to my serve control and retrive data to that as like how the boundcolumn hav dataTextField like that i want to create and bound my data to the control.im struggling to it for the past wk's can u help me regd this

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2020 ASPAlliance.com  |  Page Processed at 2020-08-09 2:00:03 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search