AJAX Custom Control


Sponsored Links

73058_New Scooba® 230 Floor Washing Robot + Free Shipping!

 

AJAX Custom Control

Here we take a look at making an AJAX Custom Controls using the Microsoft AJAX library and C# with ASP.NET.

Following my articles on the Microsoft AJAX library's classes Sys.Component and Sys.UI.Control and showing how to derive from these classes to implement own own AJAX components and controls, the next step is to take the AJAX control which derives from Sys.UI.Control and upgrade this to an AJAX custom control. Well this is starting to get harder but I finally cracked this one after investigating the classes and experimenting, examining the HTML source code to see what changes occurred. This was actually a little bit harder as the Javascript was been embedded into the assembly not directly available in the page source.

Create an AJAX Custom Control

First of all I created a new Visual Studio project of the Class Library type of project. Inside this project I add references to:


System.Drawing
System.Web
System.Web.Extensions


IScriptControl

The class file itself needs to implement the interface IScriptControl. This means we need to implement the interface's methods GetScriptDescriptors() and GetScriptReferences(). The GetScriptDescriptors() method returns a collection of ScriptDescriptor objects which contain information about properties, events and the instance of the client control type. The GetScriptReferences() method is used to register client script javascript files to the control by returning a collection of ScriptReference objects.

We make a reference to a ScriptManager as we need to call the ScriptManager's RegisterScriptControl which we call in the OnPreRender event to register our client control.

ScriptControlDescriptor

The ScriptControlDescriptor class provides a way to instantiate the client control using Javascript. The class offers various methods such as AddProperty() and AddEvent() which allow you to pass in properties and events which will be used as part of the instantiation of the client control.

Here we see the whole C# class file for the custom class:


using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace MyNameSpace
{
    public class HighLightTextBox : TextBox, IScriptControl
    {
        private ScriptManager _scriptManager;

        public IEnumerable GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("MyNameSpace.HighLightTextBox",
                this.ClientID);

            descriptor.AddEvent("focus", "doSomethingOnFocus");
            descriptor.AddEvent("blur", "doSomethingOnblur");

            return new ScriptDescriptor[] { descriptor };
        }

        public IEnumerable GetScriptReferences()
        {
            ScriptReference reference = new ScriptReference();
            reference.Assembly = "HighLightTextBox";
            reference.Name = "MyNameSpace.HighLightTextBox.js";

            return new ScriptReference[] { reference };
        }

        // overrides
        protected override void OnPreRender(EventArgs e)
        {
            if (!this.DesignMode)
            {
            // look for scriptmanager
            _scriptManager = ScriptManager.GetCurrent(Page);

            if (_scriptManager == null)
                throw new Exception("Need a scriptmanager on page");

            scriptManager.RegisterScriptControl(this);
            }

            base.OnPreRender(e);
        }

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

            base.Render(writer);
        }
    }
}


So what does this ScriptControlDescriptor class actually do? Well if we look at the HTML source on the code we can take a look:


<script type="text/javascript">
//<![CDATA[
Sys.Application.add_init(function() {
    $create(MyNameSpace.HighLightTextBox, null, {"blur":doSomethingOnblur,"focus":doSomethingOnFocus}, null, $get("HighLightTextBox1"));
});
//]]>
</script>


So the ScriptControlDescriptor class creates some some Javascript onto the page which will be responsible for instantiating our AJAX custom control.

Next we need to add our Javascript code which is the implementation of the custom control. This is shown below, and is pretty much the same Javascript used in the High-Flying article on Sys.UI.Control , albeit a slight change in class name.


// Reference MicrosoftAjax.js script file in external Javascript file
///
// register new namespace
Type.registerNamespace("MyNameSpace");

// Constructor
MyNameSpace.HighLightTextBox = function (element) {

    MyNameSpace.HighLightTextBox.initializeBase(this, [element]);

    this._focusDelegate = null;
    this._blurDelegate = null;
}

MyNameSpace.HighLightTextBox.prototype = {

    // Bind and unbind to focus event.
    add_focus: function (handler) {
        this.get_events().addHandler('focus', handler);
    },
    remove_focus: function (handler) {
        this.get_events().removeHandler('focus', handler);
    },

    // Bind and unbind to blur event.
    add_blur: function (handler) {
        this.get_events().addHandler('blur', handler);
    },
    remove_blur: function (handler) {
        this.get_events().removeHandler('blur', handler);
    },

    // dispose control
    dispose: function () {

        var element = this.get_element();

        if (this._focusDelegate) {
        Sys.UI.DomEvent.removeHandler(element, 'focus', this._focusDelegate);
        delete this._focusDelegate;
    }

    if (this._blurDelegate) {
        Sys.UI.DomEvent.removeHandler(element, 'blur', this._blurDelegate);
        delete this._blurDelegate;
    }
    MyNameSpace.HighLightTextBox.callBaseMethod(this, 'dispose');
    },
    // initialize control
    initialize: function () {

        var element = this.get_element();

        if (this._focusDelegate === null) {
            this._focusDelegate = Function.createDelegate(this, this._focusHandler);
        }

        Sys.UI.DomEvent.addHandler(element, 'focus', this._focusDelegate);

        if (this._blurDelegate === null) {
            this._blurDelegate = Function.createDelegate(this, this._blurHandler);
        }

        Sys.UI.DomEvent.addHandler(element, 'blur', this._blurDelegate);

        MyNameSpace.HighLightTextBox.callBaseMethod(this, 'initialize');

    },
    _focusHandler: function (event) {
        var h = this.get_events().getHandler('focus');
        if (h) h(this, Sys.EventArgs.Empty);
    },
    _blurHandler: function (event) {
        var h = this.get_events().getHandler('blur');
        if (h) h(this, Sys.EventArgs.Empty);
    }
}
MyNameSpace.HighLightTextBox.registerClass('MyNameSpace.HighLightTextBox', Sys.UI.Control);

// notify Scriptmanager the script is loaded
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();


Embedding our Javascript file as a Resource

The Javascript file containing the logic for our custom control needs to be embedded into our Class library project, so when adding it to the project, the Javascript file's properties needs to have the 'Build Action' set to 'Embedded Resource' in Visual Studio.

Next up we need to edit the AssemblyInfo.cs file, so I added the following line of code to the AssemblyInfo.cs file:


[assembly: System.Web.UI.WebResource("MyNameSpace.HighLightTextBox.js", "text/javascript")]


So now our Javascript file becomes part of the C# class library, embedded as a resource. Build the project. This is now our AJAX Custom Control, in a .dll file we can use across ASP.NET projects.

Use our AJAX Custom Contol in ASP.NET

Now that we've created our ASP.NET AJAX Custom Control, we'll want to start using it on pages. As with other custom controls, we need to register the control, either in the web.config for use across the whole site, or just on a page for use on that page. Here in this example, I just register it on a page for now:


<%@ Register Assembly="HighLightTextBox" Namespace="MyNameSpace" TagPrefix="HighFlying" %>


So we simply use the Register directive on the ASP.NET page, and specify the Assembly and Namespace our AJAX custom control resides in, and then also specify a TagPrefix which can be anything, but is used as the tagprefix when specifying the custom control on the page, just as 'asp' prefixes the ASP.NET built-in controls.

No with my example of an AJAX custom control, which is based on the Sys.UI.Control example, I need to provide some Javascript event handlers which handle the events which get fired off from the custom control. A ScriptManager control is on the page, and then the custom control is declared at the bottom, which is where the TextBox with the enhanced AJAX capabilities will be displayed.

Here is the ASPX markup:


<asp:ScriptManager ID="ScriptManager1" runat="server" />

<script type="text/javascript">

    function doSomethingOnFocus(sender, args) {
        $get('HighLightTextBox1').style.oldborder = $get('HighLightTextBox1').style.border;
        $get('HighLightTextBox1').style.border = "1px solid #00FF00";
    }

    function doSomethingOnblur(sender, args) {
        $get('HighLightTextBox1').style.border = $get('HighLightTextBox1').style.oldborder;
    }

</script>

<HighFlying:HighLightTextBox ID="HighLightTextBox1" runat="server" ClientIDMode="Static"></HighFlying:HighLightTextBox>