다음을 통해 공유


사용자 지정 클라이언트 이벤트 만들기

업데이트: 2007년 11월

ASP.NET의 AJAX 기능에는 완벽한 다중 계층 클라이언트 이벤트 모델이 포함되어 있습니다. Sys.Application 클래스는 응용 프로그램 수준에서 이벤트를 제공합니다. Sys.WebForms.PageRequestManager 클래스는 부분 페이지 렌더링에 포함된 페이지 부분과 관련된 이벤트를 제공합니다. 컨트롤 및 동작과 같은 개별 구성 요소는 고유한 이벤트를 가집니다. 이러한 이벤트에 대한 자세한 내용은 AJAX 클라이언트 수명 주기 이벤트를 참조하십시오.

또한 ASP.NET을 사용하면 클라이언트 수명 주기에 이벤트를 추가할 수 있습니다. Sys.UI.DomEvent 클래스를 사용하면 HTML DOM(문서 개체 모델) 이벤트를 사용자 지정 ASP.NET AJAX 구성 요소에 바인딩할 수 있습니다. 또한 Sys.EventHandlerList 클래스를 사용하면 새 ASP.NET AJAX 클라이언트 이벤트를 직접 만들 수 있습니다.

DOM 이벤트에 연결

사용할 이벤트는 대부분의 경우 HTML DOM에 정의된 이벤트에 해당합니다. 예를 들어, 사용자 지정 ASP.NET AJAX 단추 컨트롤은 연결된 HTML <button> 요소의 click 이벤트를 사용할 수 있습니다. DOM 기반 이벤트를 ASP.NET AJAX 응용 프로그램이나 사용자 지정 구성 요소에 바인딩하려면 다음 예제와 같이 DomEvent 클래스의 addHandler 메서드를 사용합니다.

Sys.UI.DomEvent.addHandler(element, 'click', this.myClickHandler);

또한 다음 예제와 같이 $addHandler 바로 가기를 사용할 수 있습니다.

$addHandler(element, 'click', this.myClickHandler);

addHandler 메서드에서는 element, eventName 및 handler라는 세 개의 매개 변수를 사용합니다. element 매개 변수는 이벤트를 노출하는 DOM 요소에 대한 참조입니다. eventName 매개 변수는 DOM 이벤트 자체의 이름입니다. handler 매개 변수는 이벤트가 발생할 때 호출할 함수에 대한 참조입니다. 자세한 내용은 Sys.UI.DomEvent addHandler 메서드를 참조하십시오.

DOM 이벤트에 대한 처리기를 제거하려면 Sys.UI.DomEvent.removeHandler 메서드 또는 $removeHandler 바로 가기를 호출하여 addHandler에 전달하는 것과 동일한 매개 변수를 전달합니다.

참고:

addHandlerremoveHandler 함수에 전달되는 이벤트 이름은 "on" 접두사를 포함하지 않아야 합니다. 예를 들어 "onclick"이 아니라 "click"을 사용합니다.

사용자 지정 이벤트 처리기 추가 및 제거

사용자 지정 ASP.NET AJAX 구성 요소의 이벤트에 대한 새 이벤트 처리기를 추가하려면 Sys.EventHandlerList 클래스의 addHandler 메서드를 사용합니다. ASP.NET AJAX 이벤트 모델의 모든 클라이언트 이벤트 및 연관된 이벤트 처리기는 해당 목적을 위한 특수한 사전인 EventHandlerList 개체에 저장됩니다. 현재 Application 개체를 비롯한 모든 구성 요소는 고유한 EventHandlerList 인스턴스를 가집니다. 항목을 EventHandlerList 개체에 추가하여 새 이벤트와 이벤트 처리기를 연관된 구성 요소에 추가합니다. 다음 구문을 사용하여 이벤트를 추가합니다.

this.get_events().addHandler(event, handler);

Sys.Component 클래스의 events 속성은 해당 구성 요소에 대한 EventHandlerList 인스턴스를 반환합니다. events 속성은 Sys.UI.Control, Sys.UI.BehaviorSys.Application 클래스에 의해 상속됩니다. event 매개 변수는 처리기를 추가할 새 이벤트나 기존 이벤트의 이름입니다. handler 매개 변수는 이벤트가 발생할 때 호출할 함수에 대한 참조입니다. event 매개 변수를 새 값으로 설정하여 새 이벤트를 사전에 추가합니다.

사전에서 사용자 지정 이벤트를 제거하려면 addHandler와 동일한 매개 변수를 가지는 Sys.EventHandlerList 클래스의 removeHandler 메서드를 사용합니다.

이미 Microsoft AJAX 라이브러리에 정의된 이벤트에 처리기를 추가하려면 다음 예제와 같이 해당 이벤트에 대한 add_ 접근자를 사용합니다.

Sys.Application.add_load(myLoadHandler);

사용자 지정 이벤트 발생

사용자 지정 이벤트를 발생시키려면 EventHandlerList 인스턴스의 getHandler 메서드를 호출하여 이벤트 이름을 매개 변수로 전달합니다. 이 메서드는 해당 이벤트에 대한 처리기인 모든 함수를 집계하는 함수를 반환합니다. 다음 예제와 같이 반환된 함수를 호출하여 이벤트를 발생시킵니다.

var h = this.get_events().getHandler('myCustomEvent')
if (h) h(this, Sys.EventArgs.Empty);

규칙에 따라 이벤트 처리기는 두 개의 매개 변수인 sender 및 eventArgs를 가집니다. sender는 이벤트가 적용되는 구성 요소(일반적으로 this)입니다. eventArgs 매개 변수는 Sys.EventArgs 개체를 참조합니다. 이 개체는 마우스 좌표와 같은 이벤트에 전달되는 정보를 포함할 수 있습니다. getHandler에 의해 반환된 함수의 서명이 연관된 모든 처리기 함수의 서명과 일치할 경우 sender 및 eventArgs 매개 변수를 생략할 수 있습니다. 그러나 이전 예제와 같이 이러한 매개 변수를 포함하는 것이 좋습니다.

예제

설명

다음 예제에서는 두 개의 섹션을 가진 간단한 다중 선택 테스트를 만듭니다. 섹션의 모든 질문에 대답할 경우 섹션의 배경색이 변경됩니다. 사용자가 테스트 마지막에 단추를 클릭할 경우 정답을 맞췄는지 여부에 대한 상태 메시지가 각 질문 옆에 표시됩니다.

응용 프로그램에는 두 개의 사용자 지정 컨트롤에 대한 인스턴스가 포함되어 있습니다. Question 컨트롤은 HTML <select> 요소에 연결되고 Section 컨트롤은 하나 이상의 Question 컨트롤을 포함하는 <div> 요소에 연결됩니다. Question 컨트롤은 Sys.UI.DomEvent 인스턴스에 의해 기본 <select> 요소의 onChange 이벤트에 바인딩되는 select 이벤트를 노출합니다. Section 컨트롤은 Section 인스턴스의 모든 Question 컨트롤에 대답할 경우 사용자 정의 함수에 의해 발생하는 complete 이벤트를 노출합니다.

코드

다음 예제에서는 구성 요소 인스턴스를 만들고 이벤트를 처리하는 Default.aspx 페이지를 보여 줍니다.

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
    <title>Custom Events Example</title>
</head>
<body>
<form id="form1" >
    <asp:ScriptManager ID="ScriptManager1"  >
        <Scripts>
           <asp:ScriptReference Path="question.js" />
           <asp:ScriptReference Path="section.js" />
       </Scripts>
    </asp:ScriptManager>
    <script type="text/javascript">
    // Add handler to init event
    Sys.Application.add_init(appInitHandler);

    function appInitHandler() {
      // create components
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question1'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question2'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question3'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question4'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group1'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group2'));
    }

    function onAnswer(question) {
        // If all questions in this section answered, 
        // raise complete event
        var section = question.get_element().parentElement;
        var questions = section.children;
        $get(question.get_id() + 'Status').innerHTML = '';
        for (var i=0; i<questions.length; i++) {
            if (questions[i].selectedIndex === -1) {
                return;
            }
        }
        $find(section.id).raiseComplete();
    }

    function onSectionComplete(section) {
        // Change background color of <div>.
        section.get_element().style.backgroundColor = 'yellow';
    }

    function done() {
        // Display correct answers where needed.
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type !== 'Demo.Question') continue;
            var element = c[i].get_element();
            var answer = element.selectedIndex;
            var correct = $find(c[i].get_id()).get_correct();
            var statusElement = c[i].get_id() + 'Status';
            if (answer !== correct) {
                $get(statusElement).innerHTML = 'Incorrect. Try again.';
            }
            else
            {
                $get(statusElement).innerHTML = 'Correct.';
            }
        }
    }

    function resethandler() {
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type === 'Demo.Question') {
                var element = c[i].get_element();
                element.selectedIndex = -1;
                var answer = element.selectedIndex;
                var statusElement = c[i].get_id() + 'Status';
                $get(statusElement).innerHTML = '';
            }
            else if (type === 'Demo.Section') {
                c[i].get_element().style.backgroundColor = 'White';

            }
        }
    }
    </script>
    <h3>Addition</h3><br />
    <div id="Group1">
        2 + 2 = 
        <select id="Question1">
            <option>2</option>
            <option>22</option>
            <option>4</option>
            <option>5</option>
        </select><span id="Question1Status"></span><br />
        2 + 3 = 
        <select id="Question2" >
            <option>3</option>
            <option>23</option>
            <option>5</option>
            <option>6</option>
        </select><span id="Question2Status"></span><br />
    </div><br /> <br />   
    <h3>Subtraction</h3><br />
    <div id="Group2">
        2 - 1 = 
        <select id="Question3" >
            <option>2</option>
            <option>0</option>
            <option>1</option>
            <option>-2</option>
        </select><span id="Question3Status"></span><br />
        2 - 2 = 
        <select id="Question4" >
            <option>2</option>
            <option>-2</option>
            <option>0</option>
            <option>-4</option>
        </select><span id="Question4Status"></span><br />
    </div><br /><br />
    <input id="Submit1" type="button" value="Check Answers" onclick="done()" />
    <input id="Reset1" type="button" value="Start Again" onclick="resethandler()" />
</form>
</body>
</html>
<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" >
    <title>Custom Events Example</title>
</head>
<body>
<form id="form1" >
    <asp:ScriptManager ID="ScriptManager1"  >
        <Scripts>
           <asp:ScriptReference Path="question.js" />
           <asp:ScriptReference Path="section.js" />
       </Scripts>
    </asp:ScriptManager>
    <script type="text/javascript">
    // Add handler to init event
    Sys.Application.add_init(appInitHandler);

    function appInitHandler() {
      // create components
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question1'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question2'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question3'));
      $create(Demo.Question, {correct: '3'},
        {select: onAnswer},null, $get('Question4'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group1'));
      $create(Demo.Section, null,
        {complete: onSectionComplete},null, $get('group2'));
    }

    function onAnswer(question) {
        // If all questions in this section answered, 
        // raise complete event
        var section = question.get_element().parentElement;
        var questions = section.children;
        $get(question.get_id() + 'Status').innerHTML = '';
        for (var i=0; i<questions.length; i++) {
            if (questions[i].selectedIndex === -1) {
                return;
            }
        }
        $find(section.id).raiseComplete();
    }

    function onSectionComplete(section) {
        // Change background color of <div>.
        section.get_element().style.backgroundColor = 'yellow';
    }

    function done() {
        // Display correct answers where needed.
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type !== 'Demo.Question') continue;
            var element = c[i].get_element();
            var answer = element.selectedIndex;
            var correct = $find(c[i].get_id()).get_correct();
            var statusElement = c[i].get_id() + 'Status';
            if (answer !== correct) {
                $get(statusElement).innerHTML = 'Incorrect. Try again.';
            }
            else
            {
                $get(statusElement).innerHTML = 'Correct.';
            }
        }
    }

    function resethandler() {
        var c = Sys.Application.getComponents();
        for (var i=0; i<c.length; i++) {
            var type = Object.getType(c[i]).getName();
            if (type === 'Demo.Question') {
                var element = c[i].get_element();
                element.selectedIndex = -1;
                var answer = element.selectedIndex;
                var statusElement = c[i].get_id() + 'Status';
                $get(statusElement).innerHTML = '';
            }
            else if (type === 'Demo.Section') {
                c[i].get_element().style.backgroundColor = 'White';

            }
        }
    }
    </script>
    <h3>Addition</h3><br />
    <div id="Group1">
        2 + 2 = 
        <select id="Question1">
            <option>2</option>
            <option>22</option>
            <option>4</option>
            <option>5</option>
        </select><span id="Question1Status"></span><br />
        2 + 3 = 
        <select id="Question2" >
            <option>3</option>
            <option>23</option>
            <option>5</option>
            <option>6</option>
        </select><span id="Question2Status"></span><br />
    </div><br /> <br />   
    <h3>Subtraction</h3><br />
    <div id="Group2">
        2 - 1 = 
        <select id="Question3" >
            <option>2</option>
            <option>0</option>
            <option>1</option>
            <option>-2</option>
        </select><span id="Question3Status"></span><br />
        2 - 2 = 
        <select id="Question4" >
            <option>2</option>
            <option>-2</option>
            <option>0</option>
            <option>-4</option>
        </select><span id="Question4Status"></span><br />
    </div><br /><br />
    <input id="Submit1" type="button" value="Check Answers" onclick="done()" />
    <input id="Reset1" type="button" value="Start Again" onclick="resethandler()" />
</form>
</body>
</html>

다음 예제에서는 Demo.Question 컨트롤을 정의하는 Question.js 파일을 보여 줍니다.

Type.registerNamespace("Demo");

// Constructor
Demo.Question = function(element) {

    Demo.Question.initializeBase(this, [element]);

    // Create a delegate for the select event.
    this._selectDelegate = null;
}
Demo.Question.prototype = {

    // correct property accessors
    get_correct: function() {
        return this.get_element().name - 1;
    },
    set_correct: function(value) {
        this.get_element().name = value;
    },

    // Bind and unbind to select event.
    add_select: function(handler) {
        this.get_events().addHandler('select', handler);
    },
    remove_select: function(handler) {
        this.get_events().removeHandler('select', handler);
    },

    // Release resources before control is disposed.
    dispose: function() {

        var element = this.get_element();

        if (this._selectDelegate) {
            $clearHandlers(element);
            delete this._selectDelegate;
        }

        Demo.Question.callBaseMethod(this, 'dispose');
    },

    initialize: function() {

        var element = this.get_element();

        // Make sure no option is selected.
        element.value = ""; 

        // Attach delegate to select event.
        if (this._selectDelegate === null) {
            this._selectDelegate = Function.createDelegate(this, this._selectHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'change', this._selectDelegate);

        Demo.Question.callBaseMethod(this, 'initialize');

    },

    _selectHandler: function(event) {
        var h = this.get_events().getHandler('select');
        if (h) h(this, Sys.EventArgs.Empty);
    }
}
Demo.Question.registerClass('Demo.Question', 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");

// Constructor
Demo.Question = function(element) {

    Demo.Question.initializeBase(this, [element]);

    // Create a delegate for the select event.
    this._selectDelegate = null;
}
Demo.Question.prototype = {

    // correct property accessors
    get_correct: function() {
        return this.get_element().name - 1;
    },
    set_correct: function(value) {
        this.get_element().name = value;
    },

    // Bind and unbind to select event.
    add_select: function(handler) {
        this.get_events().addHandler('select', handler);
    },
    remove_select: function(handler) {
        this.get_events().removeHandler('select', handler);
    },

    // Release resources before control is disposed.
    dispose: function() {

        var element = this.get_element();

        if (this._selectDelegate) {
            $clearHandlers(element);
            delete this._selectDelegate;
        }

        Demo.Question.callBaseMethod(this, 'dispose');
    },

    initialize: function() {

        var element = this.get_element();

        // Make sure no option is selected.
        element.value = ""; 

        // Attach delegate to select event.
        if (this._selectDelegate === null) {
            this._selectDelegate = Function.createDelegate(this, this._selectHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'change', this._selectDelegate);

        Demo.Question.callBaseMethod(this, 'initialize');

    },

    _selectHandler: function(event) {
        var h = this.get_events().getHandler('select');
        if (h) h(this, Sys.EventArgs.Empty);
    }
}
Demo.Question.registerClass('Demo.Question', 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();

다음 예제에서는 Demo.Section 컨트롤을 정의하는 Section.js 파일을 보여 줍니다.

Type.registerNamespace("Demo");

// Constructor
Demo.Section = function(element) {

    Demo.Section.initializeBase(this, [element]);
}
Demo.Section.prototype = {

    // Create add and remove accessors fot the complete event.
    add_complete: function(handler) {
        this.get_events().addHandler("complete", handler);
    },
    remove_complete: function(handler) {
        this.get_events().removeHandler("complete", handler);
    },

    // Create a function to raise the complete event.
    raiseComplete: function() {
        var h = this.get_events().getHandler('complete');
        if (h) h(this);
    },

    // Release resources before control is disposed.
    dispose: function() {
        var element = this.get_element();
        $clearHandlers(element);
        Demo.Section.callBaseMethod(this, 'dispose');
    }
}
Demo.Section.registerClass('Demo.Section', 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");

// Constructor
Demo.Section = function(element) {

    Demo.Section.initializeBase(this, [element]);
}
Demo.Section.prototype = {

    // Create add and remove accessors fot the complete event.
    add_complete: function(handler) {
        this.get_events().addHandler("complete", handler);
    },
    remove_complete: function(handler) {
        this.get_events().removeHandler("complete", handler);
    },

    // Create a function to raise the complete event.
    raiseComplete: function() {
        var h = this.get_events().getHandler('complete');
        if (h) h(this);
    },

    // Release resources before control is disposed.
    dispose: function() {
        var element = this.get_element();
        $clearHandlers(element);
        Demo.Section.callBaseMethod(this, 'dispose');
    }
}
Demo.Section.registerClass('Demo.Section', 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();

참고 항목

작업

사용자 지정 AJAX 클라이언트 컨트롤 만들기

참조

Sys.Application 클래스

Sys.WebForms.PageRequestManager 클래스

Sys.UI.DomEvent 클래스

Sys.EventHandlerList 클래스