Jul 31, 2007

Create Custom ASP.NET AJAX Non-Visual Client Components


  • Derive from the component base class
  • Typically have no UI representation, such as timer component that raise events at intervals but is not visible on the page.
  • Have no associated DOM elements
  • Encapsulate client code that is intended to be resuable across applications


  • Derive from the behavior base class, wich extend the Component base class
  • Extend the behavior of DOM elements, such as a watermarking behavior of the DOM element that they are associated with.
  • Can create UI elements, although they do not typically modified the basic of DOM element that they are associated with.
  • If assigned an ID, can be accessed directly from the DOM element through a custom attribute( expando).
  • Do not require an association with another client object, such as a class derived from the Control or Behavior classes.
  • Can reference either a control or a non-control HTML element in their element property.


  • Derive from the Control base class, which extends the Component base class.
  • Represent a DOM element as a client object, typically changing the original DOM element's ordinary behavior to provide new functionality. For example, a menu control might read >li< items from a >ul< element as its source data, but not display a bulleted list.
  • Are accessed from the DOM element directly through the control expando

Please refer this artical, in summary you need to do the following thing

  • You need to create an component in js file
  • add reference to the js file
  • create the component instance in the application load event, the instance will be associated with other element in the page because the information is passed in the creation method.


            Demo.Timer = function() {
            this._interval = 1000;
            this._enabled = false;
            this._timer = null;}

            Demo.Timer.prototype = {

            // OK to declare value types in the prototype
            get_interval: function() {
            /// Interval in milliseconds
            return this._interval;    },

            set_interval: function(value) {
            if (this._interval !== value) {
            this._interval = value;
            if (!this.get_isUpdating() && (this._timer !== null))
            }        }    },

            get_enabled: function() {
            /// True if timer is enabled, false if disabled.
            return this._enabled;    },

            set_enabled: function(value) {
            if (value !== this.get_enabled()) {
            this._enabled = value;

            if (!this.get_isUpdating())
            if (value) {
            this._startTimer();                }                else {
            this._stopTimer();                }            }        }
            },    // events    add_tick: function(handler) {
            /// Adds a event handler for the tick event.
            /// The handler to add to the event.
            this.get_events().addHandler("tick", handler);    },
            remove_tick: function(handler) {
            /// Removes a event handler for the tick event.
            /// The handler to remove from the event.
            this.get_events().removeHandler("tick", handler);    },
            dispose: function() {
            // call set_enabled so the property changed event fires, for potentially attached listeners.
            // make sure it stopped so we aren't called after disposal
            this._stopTimer();        // be sure to call base.dispose()
            Demo.Timer.callBaseMethod(this, 'dispose');    },
            updated: function() {        Demo.Timer.callBaseMethod(this, 'updated');
            // called after batch updates, this.beginUpdate(), this.endUpdate().
            if (this._enabled) {            this._restartTimer();        }    },
            _timerCallback: function() {
            var handler = this.get_events().getHandler("tick");
            if (handler) {            handler(this, Sys.EventArgs.Empty);        }
            },    _restartTimer: function() {        this._stopTimer();
            this._startTimer();    },    _startTimer: function() {
            // save timer cookie for removal later
            this._timer = window.setInterval(Function.createDelegate(this, this._timerCallback), this._interval);
            },    _stopTimer: function() {        if(this._timer) {
            window.clearInterval(this._timer);            this._timer = null;
            }    }}
            // JSON object that describes all properties, events, and methods of this component that should
            // be addressable through the Sys.TypeDescriptor methods, and addressable via xml-script.
            Demo.Timer.descriptor = {    properties: [   {name: 'interval', type: Number},
            {name: 'enabled', type: Boolean} ],
            events: [ {name: 'tick'} ]}
            Demo.Timer.registerClass('Demo.Timer', Sys.Component);
            // Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
            // invoke Sys.Application.notifyScriptLoaded to notify ScriptManager
            // that this is the end of the script.
            if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();