ASP.NET AJAXをつかってみる(2)

今回は、AjaxControlToolkitを利用して簡単なコントロールを作成してみます。
まずは、今回の主役のクライアントサイドのコードの記述していきます。作成するコントロールはTextBoxに入力されていない場合にTextBoxの背景を変えることができる拡張コントロールです。

コントロールクラスの宣言

他のコントロールの作成をそのまままねて、名前空間「MySampleAjaxControl」を作成してクラスRequiredTextBoxBehaviorというクラスを宣言します。コンストラクタ関数ではinitializeBaseを呼び出しメンバ変数を初期化しておきます。initializeBaseはTypeオブジェクトで宣言されているもの*1で、コンストラクタ関数共通で利用できるメソッドです。処理は前回書いたとおり継承元のクラスのprototypeに定義されたプロパティ・メソッドを自クラスのprototypeにコピーしてコンストラクタ関数を呼び出します。これを継承が複数回行われている場合には再帰的に繰り返します。

//名前空間の登録
Type.registerNamespace('MySampleAjaxControl');

//クラス(コンストラクタ関数)の宣言
MySampleAjaxControl.RequiredTextBoxBehavior = function(element) { 
	MySampleAjaxControl.RequiredTextBoxBehavior.initializeBase(this, [element]);

	this._errorColor = null;
	this._originalColor = null;
	this._changeHandler = null;

}

メソッドの宣言

メソッドの宣言はクラスのprototypeを上書きする方法を利用します。initializeメソッドとdisposeメソッドはSys.Componentで宣言されたものでSys.Applicationから自動的に呼び出されるようになっているようです。onChangeはTextBoxからフォーカスを抜けたときに動作する処理で、blurイベントに割付されています。ちなみに、Elementのイベントを処理する場合には、Function.createDelegateでメソッドをラップします。これは実際にはクロージャを作成しており、これによってonChangeの呼び出し時のthisが自オブジェクトになります。
set_ErrorColorとget_ErrorColorはアクセッサでここではサーバサイドで指定したプロパティをSys.Applicationが自動的に設定してくれます。

//メソッドの定義(プロトタイプに定義)
MySampleAjaxControl.RequiredTextBoxBehavior.prototype = {

	initialize : function() {
		MySampleAjaxControl.RequiredTextBoxBehavior.callBaseMethod(this, 'initialize');

	         this._originalColor = this.get_element().style.backgroundColor;

	         // フォーカス抜けるタイミングで処理をする
	         this._changeHandler = Function.createDelegate(this, this._onChange);
	         $addHandler(this.get_element(), "blur", this._changeHandler);
	
	},

	// 後処理
	dispose : function() {
		if (this._changeHandler) {
			$removeHandler(this.get_element(), "blur", this._changeHandler);
			this._changeHandler = null;
		}
		MySampleAjaxControl.RequiredTextBoxBehavior.callBaseMethod(this, 'dispose');
	},

	// 入力値が空の場合、背景色を変える
	_onChange : function(e) {
		if (this.get_element() && !this.get_element().disabled) {
			if (this.get_element().value == "") {
				this.get_element().style.backgroundColor = this.get_ErrorColor();
			} else {
				this.get_element().style.backgroundColor = this._originalColor;
			}
		}
	},
	
	// プロパティ
	get_ErrorColor : function() {
		return this._errorColor;
	},

	set_ErrorColor : function(value) {
		if (this._errorColor != value) {
			this._errorColor = value;
			this.raisePropertyChanged('ErrorColor');
		}
	}

}

コントロールクラスの登録

最後にregisterClassメソッドを利用してクラスを登録します。このときにはベースクラスも指定します。
今回指定しているAjaxControlToolkit.BehaviorBaseはコントロールに特別な動作を加えるベースクラスです。

MySampleAjaxControl.RequiredTextBoxBehavior.registerClass('MySampleAjaxControl.RequiredTextBoxBehavior', 
AjaxControlToolkit.BehaviorBase);

サーバサイドコントロールの作成

次に上記で作成したコントロールに対応するサーバサイドコントロールを作成します。今回サーバサイドでの処理がないため、プロパティの宣言のみになっています。WebResourceの宣言はアセンブリに埋め込まれたリソースをクライアントサイドから利用できるようにするためのものです。

[assembly: WebResource("MySampleAjaxControl.RequiredTextBox.RequiredTextBoxBehavior.js", 
"text/javascript")]

namespace MySampleAjaxControl
{
	[Designer("MySampleAjaxControl.RequiredTextBoxDesigner, MySampleAjaxControl")]
	[ClientScriptResource("MySampleAjaxControl.RequiredTextBoxBehavior", 
          "MySampleAjaxControl.RequiredTextBox.RequiredTextBoxBehavior.js")]
	[TargetControlType(typeof(TextBox))]
	public class RequiredTextBoxExtender : ExtenderControlBase
	{
		[ExtenderControlProperty()]
		public string ErrorColor
		{
			get
			{
				return GetPropertyStringValue("ErrorColor");
			}
			set
			{
				SetPropertyStringValue("ErrorColor", value);
			}
		}
	}
}

デザイナクラスの作成

デザイナクラスの作成もサンプルをまねていますが、クラスの宣言程度のものになっています。

namespace MySampleAjaxControl
{
	class RequiredTextBoxDesigner : ExtenderControlBaseDesigner
	{

	}
}


利用例

利用例はこんな感じです。



*1:実際にはFunctionオブジェクトに対して拡張している