다음을 통해 공유


사용자 지정 비시각적 클라이언트 구성 요소 만들기

업데이트: 2007년 11월

이 항목에서는 클라이언트 Sys.Component 기본 클래스에서 파생되는 ASP.NET의 AJAX 비시각적 클라이언트 구성 요소를 만들고 페이지에서 이 구성 요소를 사용하는 방법을 보여 줍니다.

이 자습서에서는 다음을 수행하는 방법에 대해 알아 봅니다.

  • 프로토타입 디자인 패턴을 사용하여 ECMAScript(JavaScript)의 비시각적 구성 요소 클래스를 정의합니다.

  • 비시각적 구성 요소를 Component 기본 클래스에서 파생되는 클래스로 등록합니다.

  • 비시각적 구성 요소의 기본 Component 클래스를 초기화하고 해당 메서드를 호출합니다.

  • 변경 알림을 발생시키는 속성을 만듭니다.

  • 페이지에서 구성 요소를 사용하고 구성 요소의 이벤트에 바인딩합니다.

개요에서는 비시각적 클라이언트 구성 요소로 타이머를 예로 듭니다. 타이머는 처리할 수 있는 이벤트를 발생시킵니다.

이 항목에서는 클라이언트 비시각적 구성 요소 기반 개체를 중점적으로 다룹니다. 이러한 구성 요소는 Component에서 파생되며 일반적으로 UI 표현이 없습니다. 기본 구성 요소 기능을 확장하는 두 가지 추가 형식의 ASP.NET AJAX 클라이언트 구성 요소 개체로 Sys.UI.Behavior에서 파생되는 동작과 Sys.UI.Control에서 파생되는 컨트롤이 있습니다. 다음 표에서는 구성 요소, 동작 및 컨트롤 사이의 차이점을 요약하여 보여 줍니다.

클라이언트 구성 요소 개체 형식

요약

구성 요소

  • Component 기본 클래스에서 파생됩니다.

  • 일정 간격마다 이벤트를 발생시키지만 페이지에는 표시되지 않는 타이머 구성 요소와 같이 일반적으로 UI 표현이 없습니다.

  • 연결된 DOM 요소가 없습니다.

  • 클라이언트 코드를 응용 프로그램 간에 다시 사용할 수 있도록 캡슐화합니다.

동작

  • Component 기본 클래스를 확장하는 Behavior 기본 클래스에서 파생됩니다.

  • 기존 텍스트 상자에 첨부할 수 있는 워터마크 동작과 같은 DOM 요소의 동작을 확장합니다.

  • 일반적으로 UI 요소가 연결된 DOM 요소의 기본 동작을 수정하지 않고도 UI 요소를 만들 수 있습니다.

  • 사용자 지정 특성(expando)을 통해 DOM 요소에서 직접 액세스할 수 있습니다. 특성 이름으로는 동작(설정된 경우) 이름이 사용되거나 그렇지 않은 경우 정규화되지 않은 형식 이름이 사용됩니다.

  • Control 또는 Behavior 클래스에서 파생되는 클래스와 같은 다른 클라이언트 개체와의 연결이 필요하지 않습니다.

  • 해당 element 속성에서 컨트롤 또는 컨트롤이 아닌 HTML 요소 중 하나를 참조할 수 있습니다.

컨트롤

  • Component 기본 클래스를 확장하는 Control 기본 클래스에서 파생됩니다.

  • 일반적으로 새 기능을 제공하도록 원래 DOM 요소의 일반 동작을 변경하여 DOM 요소를 클라이언트 개체로 표시합니다. 예를 들어 메뉴 컨트롤은 ul 요소의 li 항목을 해당 소스 데이터로 읽을 수 있지만 글머리 기호 목록은 표시하지 않습니다.

  • 컨트롤 expando를 통해 DOM 요소에서 직접 액세스합니다.

사전 요구 사항

이 항목의 예제를 실행하려면 다음이 필요합니다.

비시각적 클라이언트 구성 요소의 기본 기능 만들기

ASP.NET AJAX 비시각적 클라이언트 구성 요소는 응용 프로그램 간에 다시 사용하기 위한 JavaScript 스크립트 코드를 캡슐화합니다. 비시각적 구성 요소의 예로는 설정된 간격마다 이벤트를 발생시키는 타이머 구성 요소를 들 수 있습니다.

Component 기본 클래스에서 파생되는 사용자 지정 구성 요소는 자동으로 다음 기능을 상속합니다.

  • 클라이언트 개체 이벤트에 대한 처리기 바인딩을 관리하기 위한 브라우저 간 모델

  • 클라이언트 응용 프로그램의 구성 요소를 Sys.IDisposable 인터페이스를 구현하는 삭제 가능한 개체로 자동 등록

  • 속성이 변경되면 알림 이벤트를 발생시키는 기능

  • 구성 요소 속성 설정의 일괄 처리를 수행하는 기능. 이 기능은 개별 속성 get 및 set 접근자에서 모든 논리를 처리하는 것보다 스크립트 크기 및 처리 시간 면에서 더 효율적입니다.

  • 모든 속성 및 이벤트 수신기를 초기화하는 Sys.Component.initialize 메서드의 재정의

구성 요소 클래스에서 파생된 클라이언트 구성 요소 구현

Component에서 파생된 사용자 지정 클라이언트 구성 요소를 구현하려면 다음 단계를 수행합니다.

  • 프로토타입 디자인 패턴을 사용하여 구성 요소 클래스를 정의합니다.

  • 구성 요소의 기본 Component 인스턴스를 초기화합니다.

  • 모든 속성 접근자를 노출하고 선택적으로 propertyChanged 알림 이벤트를 발생시킵니다.

  • 이벤트 처리기 지우기와 같이 dispose 메서드를 재정의하여 리소스를 해제합니다.

다음 단원에서는 구현 단계에 대해 자세히 설명합니다.

프로토타입 디자인 패턴을 사용하여 구성 요소 클래스 정의

구성 요소 클래스를 포함하는 ASP.NET AJAX 클라이언트 클래스는 JavaScript에서 프로토타입 디자인 패턴을 사용하여 정의합니다. 프로토타입 디자인 패턴을 사용하여 구성 요소 클래스를 정의하려면 다음을 수행합니다.

  • 구성 요소 클래스의 네임스페이스를 등록합니다.

  • 구성 요소의 생성자 함수를 만들고, 생성자 함수에서 private 필드를 정의하고, 해당 초기 값을 설정합니다.

  • 구성 요소의 프로토타입을 정의합니다.

  • 구성 요소 기능을 Component에서 파생되는 클래스로 등록합니다.

자세한 내용은 프로토타입 모델을 사용하여 클라이언트 구성 요소 클래스 만들기를 참조하십시오.

기본 클래스 초기화

구성 요소의 생성자 함수에서 상속된 Type.initializeBase 메서드를 호출하여 등록된 클래스의 기본 형식을 초기화합니다. 비시각적 구성 요소 클래스는 기본 형식이 Component인 클래스로 등록됩니다. Component 기본 클래스를 초기화하면 구성 요소에서 해당 메서드를 사용할 수 있게 되며 구성 요소가 AJAX 사용 ASP.NET 응용 프로그램에 삭제 가능한 개체로 자동 등록됩니다. 자세한 내용은 Sys.IDisposable 인터페이스를 참조하십시오.

Component에서 파생되는 모든 구성 요소 클래스는 생성자에서 해당 기본 클래스를 초기화해야 합니다. 일반적으로 생성자에서 다른 코드를 실행하기 전에 initializeBase를 호출합니다. 다음 예제에서는 Component에서 파생되는 비시각적 구성 요소의 생성자 함수를 보여 줍니다.

Samples.SimpleComponent = function()
{
    Samples.SimpleComponent.initializeBase(this);
}

속성 정의 및 속성 변경 알림 발생시키기

페이지 개발자가 가져오거나 설정할 수 있는 구성 요소 클래스의 속성을 정의합니다. Component에서 파생되는 ASP.NET AJAX 구성 요소는 Sys.Component.raisePropertyChanged 메서드를 상속하며, 이 메서드는 구성 요소의 속성에 대한 propertyChanged 이벤트를 발생시키기 위해 호출합니다. 그러면 이 구성 요소를 사용하는 페이지 개발자가 구성 요소를 이러한 이벤트에 바인딩할 수 있습니다. 자세한 내용은 사용자 지정 구성 요소 속성 정의 및 PropertyChanged 이벤트 발생시키기를 참조하십시오.

속성 및 이벤트 수신기 초기화

사용자 지정 구성 요소에서 모든 속성이나 이벤트 수신기를 초기화해야 하는 경우에는 구성 요소의 프로토타입에서 Sys.Component.initialize 메서드를 재정의해야 합니다. 예를 들어 Component에서 파생되는 비시각적 구성 요소에서 대리자를 window.onFocus와 같은 이벤트에 할당할 수 있습니다. 마지막 단계로 구성 요소의 기본 클래스가 초기화를 완료할 수 있도록 기본 initialize 메서드를 호출합니다.

ASP.NET에서는 구성 요소 및 DOM 요소에 대한 표준 이벤트 관리를 위한 클래스 및 메서드를 제공합니다. 구성 요소의 이벤트를 관리하려면 Sys.EventHandlerList 클래스를 사용합니다. 예를 들어 Sys.EventHandlerList.addHandler 메서드를 사용하여 이벤트를 바인딩하고 Sys.EventHandlerList.removeHandler 메서드를 사용하여 이벤트를 해제합니다. 자세한 내용은 Sys.EventHandlerList 클래스를 참조하십시오.

DOM 요소 또는 window 개체에 대한 이벤트 처리기를 관리하려면 Sys.UI.DomEvent 클래스를 사용합니다. 예를 들어 Sys.UI.DomEvent addHandlerSys.UI.DomEvent removeHandler 메서드를 사용하여 이벤트 처리기를 바인딩 및 바인딩 해제할 수 있습니다. 자세한 내용은 Sys.UI.DomEvent 클래스를 참조하십시오.

리소스 해제

사용자 지정 구성 요소에서 구성 요소를 삭제하기 전에 리소스를 해제해야 하는 경우 dispose 메서드를 재정의하고 재정의된 메서드에서 리소스를 해제합니다. 이렇게 하면 구성 요소가 삭제되기 바로 전에 리소스가 해제됩니다. 해제해야 하는 리소스에는 DOM 이벤트에 대한 처리기가 포함될 수 있습니다. DOM 요소와 구성 요소 개체 간에 있을 수 있는 순환 참조가 모두 제거되는지 확인하여 메모리에서 개체를 제거할 수 있는지 확인합니다. 자세한 내용은 구성 요소 리소스 해제를 참조하십시오.

페이지에서 비시각적 구성 요소 사용

ASP.NET AJAX 응용 프로그램 페이지에서 사용자 지정 클라이언트 구성 요소를 사용하려면 다음을 수행합니다.

  • 웹 페이지에서 구성 요소의 스크립트 라이브러리를 등록합니다.

  • 구성 요소 인스턴스를 만듭니다.

다음 단원에서는 이러한 단계에 대해 자세히 설명합니다.

웹 페이지에서 구성 요소의 스크립트 라이브러리 등록

ScriptManager 컨트롤을 사용하여 페이지의 클라이언트 컨트롤에 필요한 스크립트를 선언적으로 또는 프로그래밍 방식으로 등록할 수 있습니다. 다음 예제에서는 구성 요소 스크립트를 등록하는 ScriptManager 컨트롤의 선언 태그를 보여 줍니다.

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

asp:ScriptManager 요소는 asp:ScriptReference 요소를 scripts 노드 내에 포함합니다. asp:ScriptReference 요소의 path 특성은 구성 요소 클래스를 정의하는 .js 파일(이 예제에서는 DemoTimer.js)의 경로를 참조합니다. 자세한 내용은 동적으로 스크립트 참조 할당ScriptManager 클래스 개요를 참조하십시오.

ScriptManager 컨트롤을 사용하여 스크립트 파일을 등록하는 대신 IScriptControl 인터페이스를 구현하는 사용자 지정 서버 컨트롤을 사용하여 클라이언트 구성 요소를 관리할 수도 있습니다. 사용자 지정 서버 컨트롤은 필요한 구성 요소 스크립트를 자동으로 등록하고 구성 요소 속성 및 이벤트 바인딩을 설정하기 위한 선언 태그를 노출할 수 있습니다. 사용자 지정 서버 컨트롤을 사용하여 스크립트를 등록하면 페이지 개발자가 사용자 구성 요소를 더욱 쉽게 사용할 수 있습니다. 자세한 내용은 IScriptControl 클래스 개요를 참조하십시오.

참고:

ScriptManager 컨트롤을 사용하여 등록할 모든 독립 실행형 스크립트 파일은 notifyScriptLoaded 메서드를 호출하여 스크립트 로드가 완료되었음을 응용 프로그램에 알립니다. 어셈블리에 포함되는 스크립트에서는 대부분의 경우 이 메서드를 호출하지 않습니다. 자세한 내용은 Sys.Application.notifyScriptLoaded 메서드를 참조하십시오.

사용자 지정 구성 요소 인스턴스 만들기

Sys.Component.create 메서드 또는 $create 바로 가기를 호출하여 클라이언트 구성 요소를 인스턴스화합니다. $create 메서드에 매개 변수를 전달하여 구성 요소 형식을 지정합니다. 또한 필수 ID 값과 선택적 초기 속성 값 및 선택적 이벤트 처리기 바인딩을 포함하는 JSON 개체도 전달합니다.

다음 예제에서는 $create 메서드를 호출하여 구성 요소 인스턴스를 인스턴스화하는 방법을 보여 줍니다.

var app = Sys.Application;
app.add_init(applicationInitHandler);

function applicationInitHandler(sender, args) 
{
    $create(Demo.Timer, {enabled:true,id:"demoTimer1", interval:2000}, 
        {tick:OnTick}, null);
}

자세한 내용은 Sys.Component.create 메서드Sys.Component $create 메서드을 참조하십시오.

사용자 지정 Demo.Timer 구성 요소 만들기

이 단원에서는 Component 기본 클래스를 확장하는 Demo.Timer라는 사용자 지정 클라이언트 구성 요소를 만든 다음 페이지에서 이 구성 요소를 사용합니다. Demo.Timer는 tick 이벤트를 정의하고 enabled 속성 및 interval 속성을 노출하고 interval 속성에 대한 변경 알림 이벤트를 발생시키는 단순한 타이머 구성 요소입니다. Demo.Timer 구성 요소를 사용하는 페이지 개발자는 tick 이벤트를 처리할 수 있습니다. 또한 속성 변경 이벤트에 바인딩하고 interval 속성이 업데이트될 때마다 필요한 작업을 수행할 수 있습니다.

Demo.Timer 구성 요소의 코드를 작성하려면

  1. AJAX 사용 ASP.NET 웹 응용 프로그램의 루트 디렉터리에서 DemoTimer.js라는 파일을 만듭니다.

  2. 파일에 다음 코드를 추가합니다.

    Type.registerNamespace("Demo");
    
    Demo.Timer = function() {
        Demo.Timer.initializeBase(this);
    
        this._interval = 1000;
        this._enabled = false;
        this._timer = null;
    }
    
    Demo.Timer.prototype = {
        // OK to declare value types in the prototype
    
    
        get_interval: function() {
            /// <value type="Number">Interval in milliseconds</value>
            return this._interval;
        },
        set_interval: function(value) {
            if (this._interval !== value) {
                this._interval = value;
                this.raisePropertyChanged('interval');
    
                if (!this.get_isUpdating() && (this._timer !== null)) {
                    this._restartTimer();
                }
            }
        },
    
        get_enabled: function() {
            /// <value type="Boolean">True if timer is enabled, false if disabled.</value>
            return this._enabled;
        },
        set_enabled: function(value) {
            if (value !== this.get_enabled()) {
                this._enabled = value;
                this.raisePropertyChanged('enabled');
                if (!this.get_isUpdating()) {
                    if (value) {
                        this._startTimer();
                    }
                    else {
                        this._stopTimer();
                    }
                }
            }
        },
    
        // events
        add_tick: function(handler) {
            /// <summary>Adds a event handler for the tick event.</summary>
            /// <param name="handler" type="Function">The handler to add to the event.</param>
            this.get_events().addHandler("tick", handler);
        },
        remove_tick: function(handler) {
            /// <summary>Removes a event handler for the tick event.</summary>
            /// <param name="handler" type="Function">The handler to remove from the event.</param>
            this.get_events().removeHandler("tick", handler);
        },
    
        dispose: function() {
            // call set_enabled so the property changed event fires, for potentially attached listeners.
            this.set_enabled(false);
            // 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;
            }
        }
    }
    
    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();
    
    

코드 설명

이 코드는 Type.registerNamespace 메서드를 호출하여 Demo 네임스페이스를 등록합니다. 생성자에서 이 예제의 interval과 같은 private 필드를 모두 선언하고 초기화하는 것이 좋습니다. 생성자는 Component 기본 클래스 메서드를 사용할 수 있도록 상속된 initializeBase 메서드를 호출합니다. 그러면 초기화된 기본 클래스에서는 Demo.Timer 인스턴스를 클라이언트 응용 프로그램에 삭제할 수 있는 개체로 등록합니다.

프로토타입에서 이 코드는 interval 및 enabled라는 두 개의 public 속성을 선언하고 초기화합니다. 속성 정의에는 해당 값을 보유하는 private 필드와 각 속성에 대한 get 및 set 접근자가 포함됩니다. 각 public 속성에 대한 set 접근자 메서드에서 이 코드는 raisePropertyChanged 메서드를 호출하여 propertyChanged 이벤트를 발생시킵니다. 이 이벤트는 속성이 변경될 때마다 페이지 개발자에게 알립니다.

페이지 개발자는 add_tick 및 remove_tick 메서드를 사용하여 tick 이벤트를 수신할 메서드를 추가 및 제거할 수 있습니다. 그러면 이러한 메서드에서는 구성 요소의 Sys.EventHandlerList 컬렉션을 통해 지정된 처리기를 추가하거나 제거합니다. EventHandlerList 개체는 상속된 Sys.Component.events 속성을 통해 구성 요소의 이벤트 처리기 컬렉션을 포함합니다. 이 예제의 코드에서는 지정된 처리기를 추가하거나 제거하기 위해 반환된 EventHandlerList 개체의 Sys.EventHandlerList.addHandlerSys.EventHandlerList.removeHandler 메서드를 호출합니다.

Demo.Timer 클래스에서는 기본 클래스의 dispose 메서드를 재정의하여 enabled 속성을 업데이트하고 소비자에게 구성 요소를 사용할 수 없음을 표시합니다. enabled 속성의 set 접근자는 propertyChanged 이벤트를 발생시켜 알림을 보냅니다. 코드에서는 private _stopTimer 메서드를 호출하여 tick 이벤트가 발생하지 못하게 합니다. 마지막으로 코드에서는 기본 dispose 메서드를 호출하여 응용 프로그램에서 구성 요소를 해제할 수 있게 합니다.

웹 페이지에서 Demo.Timer 구성 요소 사용

페이지에 있는 ASP.NET AJAX 클라이언트 구성 요소의 인스턴스는 사용자 지정 서버 컨트롤이나 웹 페이지의 클라이언트 스크립트를 사용하여 관리할 수 있습니다. 이 단원에서는 웹 페이지에서 클라이언트 스크립트를 사용하여 구성 요소 인스턴스를 만드는 방법을 알아 봅니다.

Demo.Timer 구성 요소를 사용할 페이지를 만들려면

  1. DemoTimer.js 파일을 추가한 디렉터리에서 DemoTimer.aspx라는 파일을 만들고 다음 태그와 코드를 이 파일에 추가합니다.

    <!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 >
            <title>Demo Timer Component</title>
    </head>
    <body>
        <form id="form1" > 
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                    <Scripts>
                        <asp:ScriptReference Path="DemoTimer.js"/>
                    </Scripts>
                </asp:ScriptManager>
    
                Timer Tick Count: <span id="result">0</span>
            </div>
    
            <script type="text/javascript">
    
                function OnTick(sender, args) {
                    var result = $get("result");
                    result.innerText = parseInt(result.innerText) + 1;
                }
    
                 var app = Sys.Application;
                 app.add_init(applicationInitHandler);
    
                 function applicationInitHandler(sender, args) {
                    // Create the DemoTimer component instance.  
                    // Set properties and bind events.
                    $create(Demo.Timer, 
                        {enabled:true,id:"demoTimer1",interval:2000}, 
                        {tick:OnTick}, null, null);
                }
    
            </script> 
        </form>
    </body>
    </html>
    
  2. 같은 디렉터리에서 TestDemoTimer.js라는 파일을 만들고 다음 코드를 이 파일에 추가합니다.

    function OnTick(sender, args) {
        var result = $get("result");
        result.innerText = parseInt(result.innerText) + 1;
    }
    
     var app = Sys.Application;
     app.add_init(applicationInitHandler);
    
     function applicationInitHandler(sender, args) {
        // Create the DemoTimer component instance.  
        // Set properties and bind events.
        $create(Demo.Timer, 
            {enabled:true,id:"demoTimer1",interval:2000}, 
            {tick:OnTick}, null, null);
    }
    

코드 설명

이 예제 페이지에서는 두 개의 함수 OnTick 및 applicationInitHandler를 포함하는 JavaScript 코드를 사용하여 TestDemoTimer.js 파일을 로드합니다. OnTick 함수는 Demo.Timer 구성 요소의 tick 이벤트를 처리하고 span HTML 요소에서 카운터 값을 업데이트합니다.

applicationInitHandler 함수는 app_init 이벤트에 대한 처리기입니다. 이 함수에서는 $create 메서드를 호출하고 다음과 같은 인수를 전달하여 클라이언트 스크립트에서 Demo.Timer 구성 요소를 인스턴스화합니다.

  • type 인수는 이전에 만든 Demo.Timer 클래스입니다.

  • properties 인수는 필수 구성 요소 ID 및 속성 이름과 함께 초기 값을 지정하는 속성 이름/값 쌍을 포함하는 JSON 개체로 구성됩니다. 데모용으로 타이머에서 2초마다 tick 이벤트를 발생시키도록 처음에 interval 속성을 2000밀리초로 설정합니다. 프로덕션 응용 프로그램에서는 네트워크 트래픽을 줄이기 위해 이 간격을 더 큰 값으로 설정할 것입니다. 타이머가 인스턴스화된 후 곧바로 시작되도록 구성 요소의 enabled 속성을 true로 설정합니다.

  • events 인수는 이벤트 이름과 해당 처리기가 함께 포함된 개체를 포함합니다. 이 경우 onTick 처리기는 페이지의 script 요소에 정의되어 있는 tick 이벤트에 할당됩니다.

DemoTimer.aspx 파일은 구성 요소를 호스팅하는 ASP.NET 웹 페이지입니다. 페이지의 ScriptManager 컨트롤에서 asp:ScriptReference 요소의 path 특성은 Demo.Timer 구성 요소 클래스를 정의하는 DemoTimer.js 파일의 경로를 참조합니다.

참고 항목

작업

동적으로 스크립트 참조 할당

개념

데이터 바인딩된 컨트롤에서 ASP.NET UpdatePanel 컨트롤 사용

PageRequestManager 이벤트 작업

참조

Sys.Component 클래스

ScriptManager