次の方法で共有


カスタム AJAX クライアント コントロールの作成

更新 : 2007 年 11 月

この概要では、カスタムの ASP.NET AJAX クライアント コントロールを作成し、ページで使用する方法を示します。この概要では、次の操作の実行方法について説明します。

  • ECMAScript (JavaScript) でプロトタイプ デザイン パターンを使用して、コントロール クラスを定義する。

  • コントロールを、Sys.UI.Control 基本クラスから派生したクラスとして登録する。

  • Control 基本クラスを初期化し、このクラスのメソッドを呼び出す。

  • ページ作成者が関連付けて処理できるカスタム イベントを作成する。

  • クライアント コントロールをページ内で使用し、コントロールのイベントに関連付ける。

この概要では、マウス ポインタが上に置かれたときの動作を割り当てたボタンを作成する、完全なクライアント コントロールの例を示します。

ここでは、クライアント コントロールに焦点を絞って説明します。ASP.NET AJAX クライアント コンポーネント オブジェクトには、3 つの種類があります。

  • Sys.Component 基本クラスから派生する、UI として表示されない非ビジュアルのコンポーネント

  • Sys.UI.Behavior から派生する動作

  • Control から派生するコントロール

コンポーネント、動作、およびコントロールの相違点を次の表に示します。

クライアント コンポーネント オブジェクトの種類

概要

コンポーネント

  • Component 基本クラスから派生します。

  • 通常は UI として表示されません (一定の間隔でイベントを発生させるが、ページには表示されないタイマ コンポーネントなど)。

  • 関連付けられた DOM 要素がありません。

  • 複数のアプリケーションで再利用することを目的としたクライアント コードをカプセル化します。

動作

  • Component 基本クラスを拡張した Behavior 基本クラスから派生します。

  • DOM 要素の動作を拡張します (既存のテキスト ボックスにアタッチできる透かしの動作など)。

  • UI 要素を作成できます。ただし、その要素がアタッチされた、関連 DOM 要素のマークアップは、通常は変更されません。

  • ID が割り当てられている場合は、DOM 要素からカスタムの属性 (expando) を通じて直接アクセスできます。

  • 他のクライアント オブジェクト (Control クラスや Behavior クラスから派生したクラスなど) との関連付けが不要です。

  • element プロパティで、コントロールまたはコントロール以外の HTML 要素のどちらも参照できます。

コントロール

  • Component 基本クラスを拡張した Control 基本クラスから派生します。

  • DOM 要素をクライアント オブジェクトとして表します。多くの場合、元の DOM 要素の通常の動作を変更して新しい機能を追加します。たとえば、メニュー コントロールは、ソース データとして ul 要素から li の各項目を読み取りますが、箇条書きとして表示されることはありません。

  • DOM 要素からコントロールの expando を通じて直接アクセスできます。

前提条件

このトピックで示されるクライアント コントロールの例を実行するための要件は、次のとおりです。

カスタム ASP.NET AJAX クライアント コントロールの基本機能の作成

ASP.NET AJAX クライアント コントロールは、DOM 要素をクライアント オブジェクトとして表し、マークアップ表現を拡張するか、またはその要素に機能を追加します。たとえば、別の CSS スタイルを適用することで、クライアント コントロールでマウス イベントに反応するように HTML 要素を拡張できます。

クライアント コントロールは、複数のアプリケーションで再利用することを目的とした JavaScript コードをカプセル化します。カスタム コントロールは、Control 基本クラスから派生することで、次のような多数の組み込みクロス ブラウザ機能を自動的に継承します。

  • コントロールに関連付けられている DOM 要素のイベント ハンドラ、およびコントロール自体のイベント ハンドラを追加および削除する機能。

  • Sys.IDisposable インターフェイスを実装するコントロールを、破棄できるオブジェクトとして自動的に登録する機能。

  • プロパティが変更されたときに通知イベントを発生させる機能。

  • コントロールのプロパティ設定のバッチ処理を実行する機能。この機能により、プロパティの各 get アクセサおよび set アクセサですべてのロジックを処理するよりも、スクリプトのサイズが小さくなり、処理時間も短縮できます。

クライアント コントロールの実装

次の表に、Control から派生したカスタム クライアント コントロールを実装する手順をまとめます。次の表で、各手順の詳細を説明します。

ステップ

概要

プロトタイプ デザイン パターンを使用して、クライアント コントロール クラスを定義します。

  1. コントロール クラスの名前空間を登録します。

  2. DOM 要素の引数を受け取るコンストラクタ関数をコントロールに定義し、プロトタイプを定義します。

  3. コントロールの関数を、Control 基本クラスから派生したクラスとして登録します。

コントロールの Control 基本インスタンスを初期化し、関連付けられている DOM 要素を引数として渡します。

  • コントロールのコンストラクタ内で、継承した Type.initializeBase メソッドを呼び出し、コンストラクタ引数で受け取った DOM 要素をその基本クラスに渡します。

プロパティ アクセサを公開し、必要に応じて Sys.Component.propertyChanged 通知イベントを発生させます。

  • get アクセサ メソッドと set アクセサ メソッドで、コンポーネントのプロトタイプ内のプロパティを公開します。

  • 変更通知が重要となるプロパティについては、そのプロパティの set アクセサから propertyChanged 通知イベントを発生させます。

Sys.UI.Control.initialize メソッドをオーバーライドして、プロパティとイベント リスナを初期化します。

コンポーネントまたは DOM 要素に初期化の必要なプロパティやイベント リスナがある場合は、コンポーネントのプロトタイプ内で initialize メソッドをオーバーライドします。オーバーライドしたメソッドで、以下の作業を行います。

  • Sys.UI.DomEvent.addHandler メソッドを呼び出して、window オブジェクトまたは要素の DOM イベントにデリゲートを追加します。

  • DOM 要素の初期プロパティを設定します。

  • DOM 要素でのタブ インデックスやコントロールの role 属性などのユーザー補助プロパティを設定します。

  • 基本クラスの initialize メソッドを呼び出します。

Sys.UI.Control.dispose メソッドをオーバーライドしてリソースを解放します (DOM イベント ハンドラを削除するなど)。

コントロールを破棄する前にリソースを解放する場合は、コンポーネントのプロトタイプ内で dispose メソッドをオーバーライドします。オーバーライドしたメソッドで、以下の作業を行います。

  • コントロールが内部キューに配置したプロセスを停止し、呼び出し元に公開されている機能を無効にします。

  • コントロールを破棄する前に、DOM イベント ハンドラを削除します。コントロールによって設定された DOM 要素ハンドラをクリアすることで、DOM 要素への循環参照を削除し、要素に対して予約されていたメモリを解放します。

  • dispose 基本メソッドを呼び出します。dispose メソッドの全コードは、複数回呼び出し可能であることが必要です。たとえば、リソースを解放する前に、そのリソースが既に解放されていないかを検証します。

プロトタイプ デザイン パターンを使用したコントロール クラスの定義

ASP.NET AJAX クライアント クラス (コントロール クラスを含む) は、JavaScript でプロトタイプ デザイン パターンを使用して定義されます。詳細については、「プロトタイプ モデルを使用したクライアント コンポーネント クラスの作成」を参照してください。

クライアント コントロール クラスは、Control 基本クラスから派生させる必要があります。ASP.NET AJAX クライアント クラスをクラスとしてクライアント アプリケーションに登録するには、Type.registerClass メソッドを使用します。詳細については、「Type.registerClass メソッド」を参照してください。

基本クラスの初期化

Control 基本オブジェクトは、コントロールのコンストラクタで初期化されます。コントロールのコンストラクタ内で、継承した initializeBase メソッドを呼び出し、コンストラクタ引数で受け取った DOM 要素をその基本クラスに渡します。通常は、initializeBase メソッドが呼び出されてから、コンストラクタ内で他のコードが実行されます。Control 基本クラスを初期化すると、コントロールでこのクラスのメソッドが使用できるようになり、Sys.Application インスタンスに対し、破棄できるオブジェクトとしてコントロールが自動的に登録されます。詳細については、「Sys.IDisposable インターフェイス」を参照してください。

次の例では、Control から派生するコントロールのコンストラクタ関数を示します。コンポーネントのコンストラクタによって、継承された initializeBase メソッドが呼び出されます。

Samples.SimpleControl = function(element)
{
    Samples.SimpleControl.initializeBase(this, [element]);
}

プロパティの定義とプロパティ変更通知の発生

ページ作成者が取得および設定できるプロパティを、クライアント コントロールのクラスで定義します。コンポーネントのプロパティについて、propertyChanged 通知イベントを発生させることもできます。これにより、コンポーネントを使用するページ作成者は、これらのイベントに処理を関連付けることができます。ComponentBehavior、または Control の各基本クラスから派生する ASP.NET AJAX コンポーネントは、Sys.Component.raisePropertyChanged メソッドを継承します。このメソッドは、propertyChanged イベントを発生させるために呼び出します。詳細については、「カスタム コンポーネント プロパティの定義と PropertyChanged イベントの発生」を参照してください。

プロパティおよびイベント リスナの初期化

カスタム コントロールでプロパティやイベント リスナを初期化する必要がある場合は、コンポーネントのプロトタイプ内で initialize メソッドをオーバーライドします。Control 基本クラスから派生したクライアント コントロールでは、通常、その DOM 要素イベントにハンドラが関連付けられ、DOM 要素プロパティが初期値に設定されます。最後に、initialize 基本メソッドを呼び出して、コンポーネントの基本クラスが初期化を完了できるようにします。

リソースの解放

カスタム コントロールを破棄する前にそのコントロールでリソースを解放する必要がある場合は、dispose メソッドをオーバーライドし、そのメソッド内でリソースを解放します。これにより、コントロールが破棄される直前に、リソースを確実に解放できます。解放の対象となるリソースには、DOM イベントを関連付けるために使用されるハンドラなどがあります。DOM 要素とコンポーネント オブジェクトの間に存在する可能性のある循環参照を確実に削除し、オブジェクトをメモリから削除できるようにします。詳細については、「コンポーネントのリソースの解放」を参照してください。

ページでのコントロールの使用

ASP.NET Web ページでカスタム クライアント コントロールを使用するには、次の手順を実行します。

  • Web ページでクライアント コントロールのスクリプト ライブラリを登録します。

  • クライアント コントロール インスタンスを作成します。

以降のセクションでは、これらの手順について詳しく説明します。

Web ページにおけるコントロールのスクリプト ライブラリの登録

ページ上でクライアント コントロールに必要なスクリプトを登録するには、宣言またはプログラム内で ScriptManager コントロールを使用します。

次の例では、コントロール スクリプトを登録する ScriptManager コントロールの宣言マークアップを示します。

<form id="form1" runat="server">
  <asp:ScriptManager runat="server" ID="ScriptManager01">
    <scripts>
      <asp:ScriptReference path="HoverButton.js" />
    </scripts>
  </asp:ScriptManager>
</form>

asp:ScriptManager 要素の scripts ノード内に、asp:ScriptReference 要素があります。asp:ScriptReference 要素の path 属性では、コントロール クラスを定義する HoverButton.js ファイルのパスが参照されています。詳細については、「スクリプト参照の動的な割り当て」および ScriptManager クラスの概要を参照してください。

Bb398906.alert_note(ja-jp,VS.90).gifメモ :

ScriptManager コントロールを使用して登録するスタンドアロンのスクリプト ファイルでは、notifyScriptLoaded メソッドを呼び出して、スクリプトの読み込みが完了したことをアプリケーションに通知する必要があります。ただし、アセンブリに埋め込まれたスクリプトでは、多くの場合、このメソッドを呼び出さないようにする必要があります。詳細については、「Sys.Application.notifyScriptLoaded メソッド」を参照してください。

ScriptManager コントロールを使用してスクリプト ファイルを登録する方法以外に、IScriptControl インターフェイスを実装するカスタム サーバー コントロールを使用して、クライアント コンポーネントを管理することもできます。カスタム サーバー コントロールでは、必要なコンポーネント スクリプトの登録や、コンポーネント プロパティの設定およびイベントの関連付けを行う宣言マークアップの公開を、自動的に実行できます。これにより、ページ作成者がカスタム コントロールを使用しやすくなります。詳細については、IScriptControl クラスの概要を参照してください。

カスタム コントロール インスタンスの作成

カスタム クライアント コントロールをインスタンス化するには、Sys.Component.create メソッドまたは $create ショートカットを Sys.Application.init イベントの処理時に呼び出します。次の表では、クライアント コントロールの作成時に $create メソッドに渡すパラメータを示します。

パラメータ

説明

type

コンポーネントの種類。

properties

コンポーネント ID の値およびオプションでプロパティの名前と値のペアの初期値を含んでいる JSON オブジェクト。

events

イベント名およびイベントとハンドラを関連付けたペアを含んでいる、オプションの JSON オブジェクト。

references

コンポーネントの名前と ID のペアとして渡される関連コンポーネントへの参照を含んでいる、オプションの JSON オブジェクト。

element

コントロールに関連付ける DOM 要素。

次の例では、$create メソッドを呼び出してコントロールをインスタンス化する方法を示します。

$create(Demo.HoverButton, {text: 'A HoverButton Control',element: {style: {fontWeight: "bold", borderWidth: "2px"}}}, {click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover},null, $get('Button1'));

詳細については、「Sys.Component.create メソッド」および「Sys.Component の $create メソッド」を参照してください。

カスタム HoverButton コントロールの作成

ここでは、Control 基本クラスを拡張する HoverButton という名前の単純なカスタム クライアント コントロールを作成し、そのコントロールをページで使用します。HoverButton コントロールは、関連付けられている button HTML 要素の clickfocus、および mouseover の各イベントを受け取ります。また、$create メソッドを通じて関連付けることができるイベントをコントロールに提供します。HoverButton コントロールを使用するページ作成者は、コントロールの hover イベントを関連付けることができます。

HoverButton コントロールのコードを作成するには

  1. AJAX 対応の ASP.NET Web サイトのルート ディレクトリに、HoverButton.js という名前のファイルを作成します。

  2. 次のコードをファイルに追加します。

    Type.registerNamespace("Demo");
    
    // Constructor
    Demo.HoverButton = function(element) {
    
        Demo.HoverButton.initializeBase(this, [element]);
    
        this._clickDelegate = null;
        this._hoverDelegate = null;
        this._unhoverDelegate = null;
    }
    Demo.HoverButton.prototype = {
    
        // text property accessors.
        get_text: function() {
            return this.get_element().innerHTML;
        },
        set_text: function(value) {
            this.get_element().innerHTML = value;
        },
    
        // Bind and unbind to click event.
        add_click: function(handler) {
            this.get_events().addHandler('click', handler);
        },
        remove_click: function(handler) {
            this.get_events().removeHandler('click', handler);
        },
    
        // Bind and unbind to hover event.
        add_hover: function(handler) {
            this.get_events().addHandler('hover', handler);
        },
        remove_hover: function(handler) {
            this.get_events().removeHandler('hover', handler);
        },
    
        // Bind and unbind to unhover event.
        add_unhover: function(handler) {
            this.get_events().addHandler('unhover', handler);
        },
        remove_unhover: function(handler) {
            this.get_events().removeHandler('unhover', handler);
        },
    
        // Release resources before control is disposed.
        dispose: function() {
    
            var element = this.get_element();
    
            if (this._clickDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'click', this._clickDelegate);
                delete this._clickDelegate;
            }
    
            if (this._hoverDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'focus', this._hoverDelegate);
                Sys.UI.DomEvent.removeHandler(element, 'mouseover', this._hoverDelegate);
                delete this._hoverDelegate;
            }
    
            if (this._unhoverDelegate) {
                Sys.UI.DomEvent.removeHandler(element, 'blur', this._unhoverDelegate);
                Sys.UI.DomEvent.removeHandler(element, 'mouseout', this._unhoverDelegate);
                delete this._unhoverDelegate;
            }
            Demo.HoverButton.callBaseMethod(this, 'dispose');
        },
    
        initialize: function() {
    
            var element = this.get_element();
    
            if (!element.tabIndex) element.tabIndex = 0;
    
            if (this._clickDelegate === null) {
                this._clickDelegate = Function.createDelegate(this, this._clickHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'click', this._clickDelegate);
    
            if (this._hoverDelegate === null) {
                this._hoverDelegate = Function.createDelegate(this, this._hoverHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'mouseover', this._hoverDelegate);
            Sys.UI.DomEvent.addHandler(element, 'focus', this._hoverDelegate);
    
            if (this._unhoverDelegate === null) {
                this._unhoverDelegate = Function.createDelegate(this, this._unhoverHandler);
            }
            Sys.UI.DomEvent.addHandler(element, 'mouseout', this._unhoverDelegate);
            Sys.UI.DomEvent.addHandler(element, 'blur', this._unhoverDelegate);
    
            Demo.HoverButton.callBaseMethod(this, 'initialize');
    
        },
        _clickHandler: function(event) {
            var h = this.get_events().getHandler('click');
            if (h) h(this, Sys.EventArgs.Empty);
        },
        _hoverHandler: function(event) {
            var h = this.get_events().getHandler('hover');
            if (h) h(this, Sys.EventArgs.Empty);
        },
        _unhoverHandler: function(event) {
            var h = this.get_events().getHandler('unhover');
            if (h) h(this, Sys.EventArgs.Empty);
        }
    }
    Demo.HoverButton.registerClass('Demo.HoverButton', Sys.UI.Control);
    
    // 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();
    
    

コードの説明

コードでは、Type.registerNamespace メソッドを呼び出すことにより、Demo 名前空間を登録します。コンストラクタは、継承した initializeBase メソッドを呼び出して、Control 基本クラスのメソッドを使用できるようにします。初期化された基本クラスは、クライアント アプリケーションに対し、Demo.HoverButton のインスタンスを破棄できるオブジェクトとして登録します。

プロトタイプでは、click、hover、および unhover のパブリック イベントが宣言されます。ページ作成者は、これらのイベントをリッスンするハンドラを追加および削除できます。これらのメソッドでは、コントロールのイベント ハンドラ コレクションを通じて、指定されたハンドラの追加または削除が行われます。コントロール クラスでのハンドラの追加と削除は、コントロールの Sys.EventHandlerList オブジェクトを通じて行います。EventHandlerList オブジェクトには、継承した Sys.Component.events プロパティを通じて、コントロールのイベント ハンドラのコレクションが格納されます。例では、ハンドラを追加または削除するために、返された EventHandlerList オブジェクトの Sys.EventHandlerList.addHandler メソッドと Sys.EventHandlerList.removeHandler メソッドが呼び出されます。

HoverButton クラスは、dispose 基本メソッドをオーバーライドすることで、コントロールが破棄される前にすべてのコントロール リソース (DOM イベントのハンドラなど) を安全に破棄します。最後に、dispose 基本メソッドが呼び出され、アプリケーションがコントロールを解放できるようになります。

Web ページにおける HoverButton コントロールの使用

ここでは、Web ページ内でクライアント スクリプトを使用してコントロールのインスタンスを作成する方法を説明します。

HoverButton コントロールを使用するページを作成するには

  1. HoverButton.js ファイルを配置したアプリケーションのルート ディレクトリに、DemoHoverButton.aspx という名前のファイルを作成します。

  2. このファイルに次のマークアップとコードを追加します。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head id="Head1" runat="server">
    
        <style type="text/css">
            button {border: solid 1px black}
            #HoverLabel {color: blue}
        </style>
        <title>Control Demo</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div id="ResultDisplay"></div>
    
                <asp:ScriptManager runat="server" ID="ScriptManager01">
                    <scripts>
                       <asp:ScriptReference Path="HoverButton.js" />
                    </scripts>
                </asp:ScriptManager>
    
                <script type="text/javascript">
                    var app = Sys.Application;
                    app.add_init(applicationInitHandler);
    
                    function applicationInitHandler(sender, args) {
                        $create(Demo.HoverButton, {text: 'A HoverButton Control',element: {style: {fontWeight: "bold", borderWidth: "2px"}}}, {click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover},null, $get('Button1'));
                    }
    
                    function doSomethingOnHover(sender, args) {
                        hoverMessage = "The mouse is over the button."
                        $get('HoverLabel').innerHTML = hoverMessage;
                    }
    
                    function doSomethingOnUnHover(sender, args) {
                       $get('HoverLabel').innerHTML = "";
                    }
    
                    function start(sender, args) {
                       alert("The start function handled the HoverButton click event.");
                    }
                </script>
    
                <button type="button" id="Button1"></button>&nbsp;
            <div id="HoverLabel"></div>
        </form>
    
    </body>
    </html>
    

コードの説明

DemoHoverButton.aspx ファイルは、カスタム コントロールをホストする ASP.NET Web ページです。このページでは、カスタム コントロールにバインドされている関数が、script 要素で定義されます。Sys.Application.init イベント ハンドラでは、$create メソッドを呼び出すことで、クライアント スクリプトで HoverButton コントロールがインスタンス化されます。コードでは、$create メソッドに次の引数が渡されます。

  • 引数 type には、前の手順で作成した Demo.HoverButton クラスが含まれています。

  • 引数 properties には、必須のコントロール ID 値の後に、プロパティ名の初期値を指定するプロパティの名前と値のペアが格納された JSON オブジェクトを指定します。

  • 引数 events には、イベント名とそのハンドラを組み合わせたオブジェクトを指定します。

ScriptManager コントロールでは、asp:ScriptReference ノードの path 属性で、Demo.HoverButton コントロール クラスを定義する HoverButton.js ファイルのパスが参照されています。

DOM 要素のイベント ハンドラおよびコンポーネントのイベント ハンドラの設定

ASP.NET の AJAX 機能には、コンポーネントおよび DOM 要素で標準的なイベント管理を可能にするクラスが含まれます。コントロールのイベントを管理するには、Sys.EventHandlerList クラスのメンバである addHandlerremoveHandler などを使用します。詳細については、Sys.EventHandlerList クラスの概要を参照してください。

DOM 要素または window オブジェクト イベントのイベント ハンドラを管理するには、Sys.UI.DomEvent クラスの静的メソッド、addHandler、または removeHandler を使用します。詳細については、Sys.UI.DomEvent クラスの概要を参照してください。

DOM 要素のプロパティへのアクセス

Sys.UI.DomElement クラスには、クライアント コントロールおよびクライアント要素に対する CSS クラスの関連付けの追加、削除、および切り替えを行うためのメンバが含まれています。これらのメンバを使用して、DOM 要素のプロパティに標準的なアクセスを行うこともできます。詳細については、「Sys.UI.DomElement クラス」を参照してください。

参照

処理手順

カスタムの非ビジュアル クライアント コンポーネントの作成

スクリプト参照の動的な割り当て

概念

ASP.NET UpdatePanel コントロールとデータ バインド コントロールの使用

PageRequestManager のイベントの処理

参照

Sys.Component クラス

ScriptManager