Publish Article

ASP.Net Server Controls - Up-Down or Spinner Control

Updown Server Control

As the title of the article says, we will attempt to explain the steps for creating a web control and in particluar an up-down control. The functionlaity of this control is same as MFC's Up-Down control and Window Form's System.Windows.Forms.NumericUpDown control. We will try to explain the steps in as much as details as we can. A lot of information is available in .NET framework documentation. It is just how do you apply that information to create a control that can be useful for your day to day operations on the weg pages.

There are two ways that you use to build your server control.

  • Composite Control
  • Custom Control

We will not go into details of defining these two types. There is some good information available in .NET framework documentation about it. Stating it simply, Composite Constol is a server control that utilizes one or more existing server controls. And Custom Control is very much like implementing your windows controls where you will handle the drawing by providing implementation in OnPaint event. Similarly for Custom Controls, you will provide your own rendering of control in Render event handler. We will discuss these details later in the article.

Why did we create custom control?

If you look at the Up-Down control, it is made up of one textbox and two buttons to increment or decrement the value. That means this can be accomplished using creating a composite control made up of one asp:TextBox and two asp:ImageButton controls. But we decied to create custom control and do our won redering of HTML tags.

We had couple of reason to go this route. Although ASP.Net documentation states that the server controls can generate a browser compatible HTML tags. But in our real expereince we have observred that for browsers other than Internet Explorer, the HTML code genration has been very inconsistent. The other reason is that the control value will be chnaged with every click on spinner controls. That means we will have to manage the state on client side instead of doing post backs for every click. That is not a very efficient solution because it generates a lot of network traffic. So we will have to emit client side javascript for managing state.

Lets get started

Define control

Every server control is derived from Control or WebControl. So the first step is creating a control class that derives from one of these classes. WebControl itself is derived from Control class. The advanatage of deriving your control's class is that along with the common properties of Control, your control will inherit the implementation of very commonly properties of web controls e.g. Width, Height, Font etc. So we decied to take advantage of it and derive our control WebControl class.

[ToolboxData("<{0}:UpDownControl Runat=server>/>")]
public class UpDownControl : WebControl, IPostBackDataHandler

You must have observed that we have speciifed the the control will provide impelementation of IPostBackDataHandler interface. The reason for doing is that our control will be saving the value that user has specified by incrementing or decrementing through spinners and these value has to be coneyed to the page when Form is posted back for processing. The IPostBackDataHandler interface provides two metods LoadPostData and RaisePostDataChangedEvent that our control will implement to handle the post back events from the containing page.

What properties to define?

Now lets see what all custom properties that we will need other than the standard ones like Color, Font, etc. Since our control is an Up-Down control, that means we require some graphics to display our up and down arrows. So we have two properties that can be used to set/get URL s for the up-down arrows.

 Description("URL for up arrow image")]
public string UpArrowImgUrl
	get{return this.m_strUpArrowImg;}
	set{this.m_strUpArrowImg = value;}

Then we need to provide some means of controlling, on which side of the text box, the up-down arrows should be displayed. It will be either left or right. So we need to define a property that will get/set this value. Instead of just using int type, we decied to use an enum so that this value can be set descriptively, meaning instead of setting the value as 0 or 1, we will set it by "Left" and "Right" values.

Then we need to provide some means of controlling, on which side of the text box, the up-down arrows should be displayed. It will be either left or right. So we need to define a property that will get/set this value. Instead of just using int type, we decied to use an enum so that this value can be set descriptively, meaning instead of setting the value as 0 or 1, we will set it by "Left" and "Right" values.

public enum ArrowsPosition 
	Left = 0,
	Right = 1,

Description("Specify if up-down arows will be displayed on right side or not.")]
public ArrowsPosition ArrowsPositionSide
	get{return this.m_enumArrowsPosition;}
	set{this.m_enumArrowsPosition = value;}

Next we need to specify how far the arrows will be placed from the text box. This is like providing spacing between two two HTML objects. So we deined property ArrowsSpacing that cab bet set/get.

Description("Specify the spacing between text-box and up-down arrows.")]
public int ArrowsSpacing
	get{return this.m_iArrowsSpacing;}
	set{this.m_iArrowsSpacing = value;}

Then the properties that affect the values that are saved in the text box. Like System.Windows.Forms.NumericUpdown we have specified properties that control min-max and increment values. For more details, look at the source control provided with the article.

Rendering of control

To render HTML tags for your custom server control it is very essential that you provide implementation of this method in your control class. This metod proides chance to the control to render its contents or what ever it wants to emit to display on the browser. Render method has only one parameter HtmlTextWriter which acts as an output stream to write the HTML contents to the web page.

protected override void Render(HtmlTextWriter output)

Therefore in this method we render all the HTML tags to display the text box and up-down arrow images. We emit input and img for rendering these user interfaces. And for displaying the right kind of image, we get the value from UpArrowImgUrl and DownArrowImgUrl properties. This rendering has been implemented in two private methods AddTextSpanSection and AddImageSection of the control class.

strRender.Append("\n<table cellspacing=\"0px\" cellpadding=\"0px\"");
strRender.Append(" height=\"");
strRender.Append(this.Height + "\">");
// Add up arrow row
strRender.Append("\n<td valign=\"bottom\">");
strRender.Append("<img border=0 title=\"Increment value\" src=\"");
strRender.Append(" onclick=\"javascript:" + this.UpArrowClickFunction + "();");

Handle events

Rendering just one part of impleemnting a server control. It is like providing a body to a human being. Now this thing needs a brain too. And in the world of web page controls, the brain power is to react to various actions that happen to it. We are implementing a up-down spinner control, that meams the control has to react to user's click on up-down arrows. We provide this ability bt implementation for onclick event of each img tag that displays arrows. If you look at the code above, we call UpArrowClickFunction during rendering of img control. This private method returns name of the client side javascript function that handled click event on the up-arrow image control. The same way we add client-side event handlers for down-arrow image control click event.

strRender.Append("<img border=0 title=\"Decrement value\" src=\"");
strRender.Append(" onclick=\"javascript:" + this.DownArrowClickFunction + "();");

Managing state of the control

The Up-down control has no way of raising post back events. Its not toally true, but we don't want this control to do post backs for every click on the arrow images. This emas we will have manage state using some clsine side scripts. But first we need some place holder wherr we can save the state. We use the old trick of using hidden input control on the page. This input will be used to convey the value stored in the text box to the page when user submits the form or any other control fires postback event.

ASP.Net framework helps in accomplishing this task. There is RegisterHiddenField method on Page class that automatically registers a hidden field on the form. And when the page is rederend, this hidden field is rendered on the page too. We call this method in OnPreRender event handler. RegisterHiddenField method has two arguments, one is used to specify the unique ID for the hidden controland the second argument is used to store the initial value for the control.

protected override void OnPreRender(EventArgs args)
	if (Page != null)
		Page.RegisterHiddenField(HelperID, Text);

In the control implementation, we have provided a private property, HiddenID, which uses ClientID property of the control to generate a unique ID for the hidden variable.

How is state communicated to page?

OK, we have renderd the control, handled the click events on arrows and managed the state. Now the last thing that is left, how does the change in control's state will be communicated and if the control wants to raise any event if its state has changed how will that happen? Here are the steps that need to be followed to wire this all up.

  • The first step is to tell the containing page that our control needs to be notified when post back happens. And .NET framework, the callbacks are accomplished through events and delegates. Page class has a method RegisterRequiresPostBack that needs to called and handed reference to our control. This method calls registers our control with Page for ecieving events.
    protected override void OnInit(EventArgs e)
    	if (Page != null)
  • After registering the control with Page, now we need to figure out what are we going to do with the event. And most important, how this all happens. In the start of the article when control was defined, we mentioned that control class will implementIPostBackDataHandler interface. When the Page raises postback event for the control, it calls LoadPostData method on the control. This method has two parameters. The send parameter contains the collection of all the values that have posted back. Get the posted value from this collection. And then you can compare the posted value with the current value to check if the value has changed or not. If the value has changed, return true from this method indicating that stae has changed. This will raise chnage event on the control.
    bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
    	string presentValue = this.Text;
    	string postedValue = postCollection[HiddenID];
    	if (!presentValue.Equals(postedValue))
    		this.Text = postedValue;
    		return true;
    	return false;
  • If LoadPostDatamethod returns true, the Page will call RaisePostDataChangedEvent on the control giving it a chance to raise its own evetn or do what ever processing it needs to do.

How to use this control on your page?

In the page where you want to use this control, the first step is to register it at the top of the page, using @Register directive.

<%@ Register TagPrefix="ThirdEye" Namespace="ThirdEye.WebControls" Assembly="ThirdEye.WebControls"%>

And then include in the page like other server controls. And specify the property values that you want to assign to the control.

<form id="UpDownControlClient" method="post" runat="server">

What's New?

The implementation of the control has been enhanced to provide more control on the look of this server control. Also the rendering methods use the framework specified methods on HtmlTextWrite class instead of building the string from scratch.

Go Freelance
Home     About us     Contact us    Copyright    Privacy Policy    Return Policy    Advertisers
Copyright © Netomatix