메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

ASP.NET AJAX의 세 가지 얼굴 - (2)

한빛미디어

|

2007-04-09

|

by HANBIT

11,348

제공 : 한빛 네트워크
저자 : Jesse Liberty, Dan Hurwitz
역자 : 이대엽
원문 : The Three Faces of ASP.NET AJAX

[이전 기사 보기] ASP.NET AJAX의 세 가지 얼굴 - (1)

두 번째 얼굴: 커스텀 AJAX

만약 툴킷에서 제공해주는 익스텐더가 여러분이 필요로 하는 것과 맞지 않으면 직접 여러분만의 익스텐더를 만들 수도 있다. AJAX는 여러분이 그러한 익스텐더를 만드는 것을 보조해 주며, 우리가 앞의 예제에서 자유롭게 이용했던 툴킷을 포함하여 가이드 라인도 제공해 준다.


여러분만의 AJAX Control Extender를 작성하려면 여러분은 비주얼 스튜디오 2005를 사용해야만 한다. Visual Web Developer (무료 다운로드)에서는 작동하지 않을 것이다.

앞서 작성했던 예제의 한 가지 제한사항은 실질적으로 TextChanged 이벤트가 발생하는 시점인 TextBox를 벗어나기 전까지는 버튼이 사용가능 상태로 바뀌지 않는다는 점이다. 여러분이 TextBox에서 직접 키 입력을 감지하여 버튼을 그에 따라 사용가능 상태로 바뀌게 하면 더 나을 것이다.

그렇게 하려면 커스텀 AJAX Control Extender가 딱 안성맞춤이다. 커스텀 AJAX Control Extender를 작성하려면 ToolkitExtenders 웹사이트를 새로운 웹사이트로 복사한 다음 CustomExtender를 호출한다.


여러분이 웹 사이트를 복사할 때 .dll 파일과 Register 지시자가 제대로 복사되지 않을 수도 있다. 그렇게 되더라도 좌절하지 말라. 단순히 ConfirmButtonExtender를 선택하고 Ctrl-X를 눌러 그것을 삭제한다. 그렇게 한 다음 새로운 ConfirmExtender를 그 자리에 끌어다 놓으면 새 ConfirmExtender가 등록되고 .dll 파일들이 제 자리에 놓여지게 될 것이다. 그리고 나서 새로 추가한 것들을 선택하고 Ctrl-V를 눌러 여러분이 삭제했던 것들로 덮어쓰면, 짜잔! 이전 것들이 제대로 동작할 것이다.

여러분의 복사본을 만든 후 곧장 솔루션에 오른쪽 버튼을 눌러 “새 프로젝트 추가”를 선택한다. “새 프로젝트 추가(Add New Project)” 대화상자의 “내 템플릿(My Template)” 영역에서 “ASP.NET AJAX Control Project”를 선택한다. 새 프로젝트의 이름을 그림 6에 나타나 있는 것과 같이 ChangeAwareButton이라 입력한다.


만약 여러분이 비주얼 베이직이 아닌 다른 언어로 작업하길 원한다면 대화상자에서 알맞은 프로젝트 형식을 펼쳐보라.


[그림 6] 웹 사이트에 AJAX Control Project 추가 (확대하려면 클릭하시오)

이렇게 하면 프로젝트가 웹 사이트에 추가될 것이며 그 프로젝트는 그림 7의 솔루션 탐색기에 나타나 있는 것과 같이 몇 가지 자동으로 생성된 파일들(ChangeAwareButtonBehavior.js, ChangeAwareButtonDesigner.vb, ChangeAwareButtonExtender.vb)을 포함할 것이다.


[그림 7] AJAX Control Project를 보여주고 있는 솔루션 탐색기

자바스크립트 파일은 여러분이 작성하는 코드가 대부분을 차지할 것이다. 이 파일은 클라이언트에서 실행되는 스크립트를 포함하고 있는데, 컨트롤의 로직과 행위(따라서 그러한 파일명을 갖게 되는 것이다)를 구현하고 있다.

“Designer”로 끝나는 VB 파일은 “디자인 타임 기능(design time functionality)”을 가능하게 해주는 클래스를 포함하는데 일반적으로 여러분이 직접 수정하지는 않는다.

여러분은 ChangeAwareButtonExtender.vb 라는 다른 VB 파일에 코드를 작성할 것이다. 이 파일은 서버측 클래스이며 익스텐더가 생성되도록 한다. 그것은 또한 여러분이 컨트롤 익스텐더를 만들고 그것의 속성에 접근할 수 있도록 해주기도 한다. 이 클래스에서 만들어진 모든 속성은 그것과 대응하는 속성이 자바스크립트 행위 파일(JavaScript Behavior file)에도 정의되어 있어야 한다.

기능 구현

Extender 파일인 ChangeAwareButtonExtender.vb를 연다. 파일을 열어보면 TargetControlType과 같은 몇 가지 ChangeAwareButtonExtender 클래스를 꾸며주는 속성이 있음을 볼 수 있을 것이다. 템플릿 코드에는 대상 컨트롤의 타입이 Control로 지정되어 있는데, 이는 어떠한 타입의 컨트롤이라도 대상 컨트롤로 지정할 수 있다는 것을 의미한다.

다음에 나타나는 코드와 같이 이 속성을 TextBox로 변경하여 대상 타입을 TextBox로 한정해 보도록 하자:
 _
 _
 _
Public Class ChangeAwareButtonExtender
    Inherits ExtenderControlBase
기본 속성명인 MyProperty를 좀 더 의미있는 TargetButtonID와 같은 것으로 변경한다. 기본 속성명을 변경할 경우 Extender 파일인ChangeAwareButtonExtender.vb에는 3군데, 자바스크립트 행위 파일인 ChangeAwareButtonBehavior.js에는 5군데를 변경해야 한다.


찾아 바꾸기를 할 경우, “단어 단위로” 검색하면 안 되는데 왜냐하면 this._MyPropertyValue를 this._TargetButtonIDValue로 변경할 것이기 때문이다.

여러분이 동적으로 버튼의 텍스트를 설정할 수 있도록 해줄 ButtonText 속성을 두 번째 속성으로 추가한다. AJAX Control Extender에 속성을 추가하기 위해서 여러분은 두 개의 파일(자바스크립트 Behavior 파일과 VB Extender 파일)을 서로 일치하도록 변경해야 한다.

먼저 다음의 public 문자열 속성에 대한 정의를 ChangeAwareButtonExtender.vb에 추가한다:
 _
 _
Public Property ButtonText() As String
    Get
        Return GetPropertyValue("ButtonText", "")
    End Get
    Set(ByVal value As String)
        SetPropertyValue("ButtonText", value)
    End Set
End Property
비록 VB가 일반적으로 대소문자를 구별하지 않기는 하지만 이 경우 속성의 이름을 대소문자를 구별하여 지었는데, 왜냐하면 자바스크립트 파일에 포함되어 있는 속성명과 정확히 일치해야 하기 때문이다.

IDReferenceProperty

이 익스텐더는 텍스트 상자를 확장할 것이며 버튼을 참조할 것이다. 그러한 사실을 프레임워크에서 명확하게 인식하기 위한 IDReferenceProperty 라는 특별한 속성이 있는데, 여러분은 TargetButtonID 속성를 기입하여 현재 참조되고 있는 것이 버튼임을 알려주어야 한다.
 _
 _
 _
Public Property TargetButtonID() As String
    Get
        Return GetPropertyStringValue("TargetButtonID")
    End Get
    Set(ByVal value As String)
        SetPropertyValue("TargetButtonID", value)
    End Set
End Property
VB 파일을 설정하고 나면, 이제는 VB 파일에 대응되는 자바스크립트 파일을 손볼 차례다. Behavior 파일인 ChangeAwareButtonBehavior.js를 열고 ChangeAwareButton.ChangeAwareButtonBehavior 함수에 한 줄을 추가한다(코드는 메소드의 마지막 줄에 추가하는데, 이것은 버튼의 텍스트 값에 대한 속성 값을 가질 새로운 멤버변수를 선언하는 코드이다)
ChangeAwarebutton.ChangeAwarebuttonBehavior = function(element) 
{
    ChangeAwarebutton.ChangeAwarebuttonBehavior.initializeBase(this, [element]);
    this._TargetButtonIDValue = null;
    this._ButtonTextValue = null;  // we added this line
마찬가지로 새로운 속성에 대한 접근자 함수도 필요할 것이다. 다음의 몇 줄의 코드는 _ButtonTextValue 값에 접근하고 설정할 수 있도록 해준다:
get_ButtonText : function() 
{
    return this._ButtonTextValue;
},
set_ButtonText : function(value) 
{
    this._ButtonTextValue = value;
},
여러분은 이 함수들을 이미 존재하는 TargetButtonID 접근자의 위나 아래에 둘 수 있다.

결론적으로, 그리고 익스텐더에서 가장 중요한 것이기도 한데, 우리는 TextBox 컨트롤의 keyup 이벤트에 응답하는 클라이언트측 메소드를 구현하길 원한다는 것이다. 서버측에는 keyup이라는 이벤트가 없지만 클라이언트측에는 있으며, 이것은 AJAX를 상당히 강력하게 만들어준다. 불행히도 Microsoft는 익스텐더에서 그 이벤트로의 접근을 제공해 주지 않는데, 결국 그것이 여기서 우리가 직접 익스텐더를 작성하고 있는 이유이기도 하다.

우리는 이것을 일반 자바스크립트로 구현할 것이며, 여러분이 “여기에 초기화 코드를 추가하십시오(Add your initialization code here)”라는 주석을 찾아볼 수 있는 프로토타입(prototype) 영역에 이벤트 선언을 작성할 것이다.
$addHandler(this.get_element(), "keyup",
   Function.createDelegate(this, this._onkeyup));
   this._onkeyup();
클래스 안의 dispose 메소드 정의가 위치한 곳 바로 아래에 메소드를 추가한다.
_onkeyup : function() 
{
    // set a local variable to represent the button
    var e = $get(this._TargetButtonIDValue);
    if (e)    // if we got the button
    {
        // set the variable disabled to whether the text box is empty
        var disabled = (this.get_element().value == "");
        
        // set the button disabled to the value of the variable
        e.disabled = disabled;
        
        // if the button has text...
        if (this._ButtonTextValue) 
        {
            // if the button is disabled
            if (disabled) 
            {
                // set the control"s old value to the current value
                this._oldValue = e.value;
                // set the current value to the button"s text value
                e.value = this._ButtonTextValue;
            } 
            else // if the button is not disabled
            {
                if (this._oldValue) // if there is an old value
                {
                    // set the text to the old value
                    e.value = this._oldValue;
                }   // end if _oldvalue
            }       // end else
        }           // end if TextValue
    }               // end if e
},                  // end on key up function
‘빌드’→’솔루션 빌드’를 클릭하여 솔루션을 빌드한다. 이렇게 하면 그림 8에 나타나 있는 것과 같이 ChangeAwareButton Components라는 이름의 새로운 영역이 도구상자의 최상단에 추가될 것이다.


[그림 8] 새로운 도구상자 영역 (확대하려면 클릭하시오)

도구상자 영역에는 ChangeAwareButtonExtender라 불리는 컴포넌트가 있을 필요가 있다. 컴포넌트가 도구상자 영역에 있으면 꽤 편리할 것이다. 컴포넌트를 페이지로 끌어다 놓는다.

만약 컨트롤을 페이지로 추가할 수 없으면 여러분이 직접 컨트롤을 페이지로 추가할 수 있다. 먼저 여러분은 Control Extender 프로젝트에 대한 참조를 웹사이트에 추가할 필요가 있다. 솔루션 탐색기의 웹 사이트에 오른쪽 버튼을 클릭한다. “참조 추가(Add Reference...) “를 그림 9에 나타나 있는 것처럼 클릭한 다음 참조 추가 대화상자의 프로젝트 탭을 클릭한다.


[그림 9] 참조 추가 대화상자의 프로젝트 탭

Default.aspx의 소스 보기로 전환하여 다음의 Register 지시자를 페이지 상단에 추가한다:
<%@ Register Assembly="ChangeAwareButton"
     Namespace="ChangeAwareButton.ChangeAwareButton " 
     TagPrefix="extndr"%>
이제 TextBox와 Button을 포함하고 있는 UpdatePanel안에 아래의 마크업 코드를 추가하여 ChangeAwareButtonExtender 컨트롤 선언을 추가한다.

ChangeAwareButtonExtender가 페이지에 추가되면 디자인 보기로 다시 전환한다. 컨트롤을 클릭한 다음 속성 창으로 이동한다.

TargetControlID 속성을 TextBox의 ID로 설정함으로써 이 익스텐더가 대상 컨트롤인 TextBox를 후킹(hook)할 것임을 기억하라.

TextBox를 클릭한다. 속성창에는 이제 ChangeAwareButtonExtender에 관련된 항목이 나타날 것이다. BehaviorID는 이미 입력되어 있을 것이며 DisabledButtonText와 TargetButtonID의 하위 속성에 그림 10에 나타나 있는 대로 값을 추가한다.


[그림 10] ChangeAwareButtonExtender의 하위 속성을 보여주고 있는 TextBox 속성

애플리케이션을 실행해 본다. 페이지는 아마 그림 11과 같이 나타날 것이다. 버튼은 기본적으로 사용불가 상태이며 버튼의 Text 속성은 ChangeAwareButtonExtender의 DisabledButtonText 속성에 입력했던 것일 것이다.


[그림 11] 초기에는 사용불가 상태로 설정되어 있는 ChangeAwareButton

아무 텍스트나 텍스트 상자에 입력하자마자 버튼이 사용가능 상태로 바뀔 것이며 그림 12에 나타나 있는 것과 같이 버튼의 Text 속성은 마크업에서 Button을 선언할 때 지정했던 원래의 값으로 뒤바뀔 것이다.


[그림 12] 텍스트 입력 후 사용가능 상태로 바뀐 ChangeAwareButton

이 예제는 앞의 예제를 토대로 작성하였기 때문에 버튼을 클릭하면 ConfirmButtonExtender가 활성화되어 사용자에게 정말로 입력한 사용자를 삭제하기를 원하는지 확인할 것이다.


실제 애플리케이션에서라면 버튼의 Click 이벤트 핸들러가 단순히 텍스트 상자를 공란으로 만드는 것 보다 훨씬 더 많은 일을 할 것이다. 아마도 실제 애플리케이션이라면 사용자를 삭제하려 하기 전에 사용자의 이름의 실제로 존재하는지를 확인할 것이다.
TAG :
댓글 입력
자료실

최근 본 상품0