Tuesday, November 8, 2011

Encapsulating an AJAX client control into a custom server control (Part 3)

The previous article was a step forward but it is still far from reusing as a server side control. What we will do in this part will make us possible to have a custom textbox control that makes al it takes to have this client-side functionality and we will be able to drag the ASP.NET control into our page.
To start with, we need a new server-side control library project that will compile as a dll and contains the server side code and embeds the client-side script. This project will have two files in it: the PassTextBox.cs which deals with the server-side TextBox and inherits from TextBox and implements the IScriptControl which makes it possible to embed the script code.
Notice in the code that the class needs to register the script with the ScriptManager which is accessible through its static method GetCurrent(Page). This is done in OnPreRender method.
In the previous article we had the css class names inside the javascript. In this example we will assign them through the controls properties. The GetScriptDescriptor method allows us to prototype our class where we define these properties.

namespace Panahy.Ajax
{
 
public class PassTextBox : TextBox, IScriptControl
  {
private ScriptManager sMgr;
public string WeakCssClass;
public string MediumCssClass;
public string StrongCssClass;
protected virtual IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
 
ScriptControlDescriptor descriptor =
   
new ScriptControlDescriptor("Panahy.Ajax.PassTextBox", this.ClientID);

  descriptor.AddProperty(
"weakCssClass", this.WeakCssClass);
  descriptor.AddProperty(
"mediumCssClass", this.MediumCssClass);
  descriptor.AddProperty(
"strongCssClass", this.StrongCssClass);
  return new ScriptDescriptor[] { descriptor };
}

protected virtual IEnumerable<ScriptReference> GetScriptReferences()
{
 
ScriptReference reference = new ScriptReference();

  reference.Assembly =
"Panahy.Ajax";
  reference.Name =
"Panahy.Ajax.PassTextBox.js";
 
return new ScriptReference[] { reference };
}

protected override void OnPreRender(EventArgs e)
{
 
if (!this.DesignMode)
  {
   
//test for the existence of a ScriptManager
   
sMgr = ScriptManager.GetCurrent(Page);

   
if (sMgr == null)
      
throw new HttpException("A ScriptManager control must exist on the page.");
    sMgr.RegisterScriptControl(this);
  }
 
base.OnPreRender(e);
}

protected override void Render(HtmlTextWriter writer)
{
 
if (!this.DesignMode)
    sMgr.RegisterScriptDescriptors(
this);
  base.Render(writer);
}

IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
 
return GetScriptReferences();
}

IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
 
return GetScriptDescriptors();
}
}
}
The javascript file remains as before.
Now we can reuse the control in any project that refers to the dll.

<%@ Register Assembly="Panahy.Ajax" Namespace="Panahy.Ajax" TagPrefix="panahyAjax" %>

<panahyAjax:PassTextBox ID="textbox1" runat="server" width="200"
   
TextMode="Password" WeakCssClass="weak" MediumCssClass="medium"
    StrongCssClass
="strong"></panahyAjax:PassTextBox>



Although this sample can be handy to use as a template for other server controls, the introduced functionality could be done by creating an AJAX Behavior for client controls, which is the topic for the next article.