[엘리의 실버라이트 2.0] Silverlight 입력 이벤트 핸들러 작성 (2) Silverlight2008/08/19 10:15
원본: http://silverlight.net/Quickstarts/BuildUi/ControlEventHandlers.aspx
본 강좌는 위의 원글을 참고 및 번역해서 작성했으며, 글 중간중간 제 개인적인 표현이나 의견을 넣어서 각색했습니다.
안녕하세요. 엘리 입니다.
입력 이벤트와 라우트된 이벤트, 입력-특화 이벤트 데이터 (Input-Specific Event Data)
이번 시간에는 이전 시간에 소개한 CLR의 관리되는 코드에서 핸들링되는 이벤트와 XAML 파일의 엘리먼트 속성을 이용하여 참조하는 방법, 다른 이벤트 핸들러를 소개할 것입니다. 이전 시간에 만든 핸들러를 수정하여 Silverlight 입력이벤트에 특화된 중요한 두 개념을 설명을 할 것입니다. (입력-특화 이벤트 데이터는 말이 좀 이상할 수 있습니다. 영문을 함께 표기했으니 의미로 파악하시면 좀 더 나을 것 같습니다. ^.^*)
StackPanel에 핸들러 추가하기
1. Page.xaml 파일을 열어서 StackPanel 엘리먼트에 MouseLeftButtonDown 이벤트의 핸들러를 추가합니다. 핸들러 명명은 인텔리센스 항목의 새 이벤트 처리기를 선택하여 LayoutRoot_MouseLeftButtonDown으로 지정된 이름을 사용하세요.
2. Canvas 엘리먼트 뒤에 StackPanel의 자식 엘리먼트로 아래의 엘리먼트를 추가합니다.
|
<TextBlock Name=”statusText”/> |
3. 다음으로는 사용하는 언어에 따라 Page.xaml.cs 또는 Page.xaml.vb 파일을 열어 LayoutRoot_MouseLeftButtonDown 핸들러에 대한 아래 코드를 추가합니다.
|
FrameworkElement fe = e.Source as FrameworkElement; StringBuilder sb = new StringBuilder(); //using System.Text; 를 선언한 후 사용합니다. sb.Append(“source: “ + fe.Name + “\n”); sb.Append(“relative x/y to source: “ + e.GetPosition(fe) + “\n”); sb.Append(“Silverlight content area x/y : “ + e.GetPosition(null)); statusText.Text = sb.ToString(); |
4. 컴파일 후 응용 프로그램을 실행시킵니다. (F5 키 이용하시는 것 기억하고 계시죠? ^^)
Canvas 엘리먼트를 클릭하세요. 이전 시간에 실행했을 때와 같이 컬러가 변경되는 것을 확인하실 수 있습니다.
그러나 이 이벤트는 부모 엘리먼트인 StackPanel에 의해 핸들링 된 것이고 마우스 이벤트 데이터에서 발생한 정보가 TextBlock 엘리먼트에 표시된 것입니다. 이것은 라우트된 이벤트를 잘 설명해주고 있는 좋은 예입니다.
Canvas 엘리먼트에 의해서 이벤트가 발생한 것이지만 부모 엘리먼트인 StackPanel의 핸들러로 전달되어진 것입니다. 루트엘리먼트인 UserControl에 핸들러를 지정해두었다면, 그 이벤트는 또한 UserControl 엘리먼트로 전달되어졌을 것입니다. 위 그림을 보셔도 Canvas1 영역을 클릭했는데 해당 이벤트 결과인 Canvas1 영역의 컬러가 변경도 되었지만 StackPanel의 이벤트 결과인 source와 각 좌표 값이 나타난 것을 볼 수 있습니다.
모든 Silverlight 이벤트가 라우팅 습성을 가지지는 않고 불과 몇몇의 입력 이벤트들만 라우트 습성을 가지고 있습니다. 이런 라우트되는 이벤트들은 UIElement 기본 클래스에 의해서 정의된 것들이고 마우스나 키보드에 의해 발생한 입력 이벤트들입니다. UIElement에 의해 정의된 이벤트에 대해 좀 더 자세히 알고 싶으시면 SDK 참고 문서를 확인하시고 특별히 라우팅 습성을 가진 이벤트들을 주의 깊게 확인해보시기 바랍니다.
LayoutRoot_MouseLeftButtonDown은 이벤트 데이터로부터 Source의 값을 받습니다. 이것이 실제로 이벤트를 발생한 엘리먼트이고 이벤트가 라우팅될 때 이벤트를 처음으로 핸들링하게 됩니다. 그리고 가끔 TextBlock의 텍스트인 “Canvas1”이나 “Canvas2”를 클릭했을 때 Source의 이름이 나타나지 않는 경우가 있습니다. 이런 현상은 현재 TextBlock 엘리먼트에 이름을 주지 않았기 때문에 “Canvas1”이나 “Canvas2”를 클릭했을 때 StackPanel에 이름을 표시하지 않는 것입니다. 그래서 실제로는 StackPanel에 핸들러가 나타나기 전에 라우팅이 일어난 것입니다.
이것은 라우팅된 입력 이벤트의 가치와 목적을 설명하는 것입니다. 여러분이 UI를 만들 때, 기존 컨틀롤과 함께 코드를 만들어가는 경우와 사용자 컨트롤의 조합물을 정의할 때 조합물의 부분으로 핸들러를 작성해야할지 조합물을 포함하고 있는 부모에 대한 코드를 작성해야 할 지는 언제나 명확하지 않습니다. 이벤트 라우팅은 각각의 경우 또는 두 경우 모두 제공합니다.
또한 LayoutRoot_MouseLeftButtonDown은 특별히 이벤트 데이터 (마우스 이벤트가 발생한 곳의 X, Y 좌표를 알려주는 데이터)와 관련된 마우스 이벤트를 가장 유용하게 보여주는 예입니다. 좌표값은 GetPosistion에서 전달 받습니다. GetPosistion은 속성이 아닌 메서드인데, 좌표의 기준이 될 틀을 지정함으로써 관련된 좌표를 쉽게 알 수 있습니다.
전체 Silverlight 영역 내의 좌표를 얻기 위해서는 간단히 GetPosition에 null 값을 주면 됩니다. 그외에 Silverlight 객체 트리에 연결된 어떤 엘리먼트도 지정해줄 수 있습니다. (이 것은 이벤트 라우트 경로에 직접적으로 포함된 객체일 필요는 없습니다.) 인자로 전달되는 대부분 일반적 객체는 이벤트 Source입니다. 그래서 핸들러가 부모 엘리먼트에서 처리되어도 마우스 이벤트가 발생한 객체의 상대적인 위치를 유지할 수 있습니다. 이외에 다른 방법들도 많이 있는데, 연관된 트랜스폼에 대해 정확히 프레임 객체에 대한 참조를 넘길 수도 있습니다.
이벤트 핸들러에서 Handled 사용하기
이벤트 라우팅은 아주 유용하지만 특정 입력 이벤트에만 라우팅되고 그 외에 다른 이벤트 핸들러에는 전달되지 않기를 원하는 경우가 있을 것입니다. 다행히 여러분은 라우팅되는 이전 시점에서 이미 다른 핸들러에 의해 호출되었던 사실을 보고할 수 있는 이벤트 핸들러를 작성할 수 있습니다. 이 것을 하기 위해 이벤트 데이터 내에 Handled의 값을 추가해야 합니다.
다음은 handler 로직에 Handled 추가하는 방법입니다.
1. Page.xaml.cs 또는 Page.xaml.vb 파일을 열어 LayoutRoot_MouseLeftButtonDown 핸들러에 Handled를 true로 설정합니다.
|
e.Handled = true; FrameworkElement fe = e.Source as FrameworkElement; StringBuilder sb = new StringBuilder(); sb.Append(“source: “ + fe.Naem + “\n”); sb.Append(“relative x/y to source: “ + e.GetPosition(fe) + “\n”); sb.Append(“Silverlight content area x/y: “ + e.GetPosition(null)); statusText.Text = sb.ToString(); //</SnippetStackPanelHandler> |
2. 다음으로는 Canvas1_MouseLeftButtonDown 핸들러에 Handled에 true 값을 추가합니다. VisualBasic 예제에서 Canvas2_MouseLeftButtonDown 핸들러를 추가하였다면 동일하게 추가합니다. statusText의 값은 빈 칸으로 둡니다. (statusText에 값 지정 시 어떤 변화가 있는지는 아무 값을 넣어보고 컴파일 후 실행보시기 바랍니다.)
|
Void Canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; statusText.Text = “”; Canvas c = sender as Canvas; SolidColorBrush newColor = new SolidColorBrush(Color.FromArgb (255, 200, 77, 0)); c.Background = newColor; } |
3. 컴파일 후 응용 프로그램을 실행합니다.
Canvas 엘리먼트를 클릭해보세요. 전에 실행했던 것처럼 컬러가 변경됩니다. 그러나 그 이벤트가 부모 엘리먼트인 StackPanel에 의해 핸들링되지는 않는다는 것을 알 수 있습니다. Canvas 핸들러가 실행되어진 후에 어떤 핸들러도 함께 라우팅이 되지 않았습니다. 이는 Handled가 true로 설정을 되었기 때문에 이벤트 라우팅이 이루어지지 않은 것입니다.
WPF (Windows Presentation Foundation)의 라우팅된 이벤트에 대해 잘 알고 있다면, 라우팅된 이벤트 시스템의 특성의 작은 차이점 있다는 것을 알 수 있을 것입니다. WPF에서는 이벤트 데이터를 Handled=true로 설정하면 대부분 핸들러를 호출되지 않게 할 수 있습니다. 그러나 “handleEventsToo” 핸들러는 Handled=true를 설정한 이벤트도 여전히 호출하게됩니다. Silverlight는 이와 비슷한 기술을 지원하지 않습니다. 이벤트 데이터를 Handled=true로 설정한 것은 항상 라우팅되지 않습니다.
키보드 이벤트
키보드 이벤트도 라우팅된 이벤트입니다. 마우스 포인터 위치 X/Y 좌표 값을 전달하듯이 키보드 이벤트 데이터 키를 누르거나 키에서 손을 뗄 때 키의 특정 값을 전달합니다
키보드 이벤트는 또한 기능 키의 개념을 가지고 있습니다. 대부분 기능 키들은 SHIFT 키 또는 CTRL 키입니다. 일반적으로 다른 키와 동시에 기능 키를 누를 때 키보드 이벤트가 발생을 하게 됩니다.
여러분이 추가한 엘리먼트는 본래부터 포커스를 가지고 있지 않습니다. 탭 순서에 따라 멈출 수 있고 포커스를 얻을 수 있는 UI 컨트롤을 추가하고 싶을 것입니다. 컨트롤은 키보드 이벤트가 발생하기 위해서 포커스 되어져야할 것이지만 키 이벤트는 컨트롤 보다 하위 단계에 정의되어 있습니다. 그래서 panel 같이 포커스를 가질 수 없는 컨트롤이 아닌 것들도 라우팅을 통해 포거스를 핸들링 할 수 있습니다.
다음은 핸들러 로직에 Handled 추가하는 방법입니다.
1. Page.xaml.cs 또는 Page.xaml.vb 파일을 열어 LayoutRoot로 명명된 StackPanel에 KeyDown 이벤트 핸들러를 추가합니다. 인텔리센스를 사용하여 LayoutRoot_KeyDown 핸들러를 추가하여 아래 코드를 코딩합니다.
|
private void LayoutRoot_KeyDown(object sender, KeyEventArgs e) { //check key value, we are looking for "G" if (e.Key == Key.G) { //check modifiers for Ctrl if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { statusText.Text = "Beep!"; } } } |
|
<Button Content=”Hello” /> |
3. 컴파일 후 응용 프로그램을 실행시킵니다.
브라우저에서 탭 키를 누릅니다. 한 번 탭 키를 누르면 Silverlight 컨텐트 내에 포커스가 있는데, 유일하게 포커스가 가능한 엘리먼트는 버튼입니다. Hello 버튼이 포커스를 가지고 있는 동안 CTRL+G 키를 누르면 부모인 StackPanel로 이벤트가 라우팅 되고 그 핸들러는 statusText를 변경하게 됩니다.
|
참고 키는 단지 포터블 키(이기종 플랫폼에서도 인식 가능한 키) 코드만 전달 가능합니다. 넌포터블 키(특정 기종 플랫폼에서만 인식 가능한 키 - SCROLL LOCK키는 Windows 플랫폼에서만 인식 가능) 코드는 허용되지 않습니다. 넌포터블 키 코드는 퀵스타트에서는 다루지 않습니다. 키보드 지원을 참고하시기 바랍니다. |
참고 사항
이 번 시간은 여기까지입니다. 다음 시간에는 Silverlight 응용 프로그램을 다운로드 받을 때 로딩되는 진행 상황 등을 알려주는 임시 (준비) 페이지 만들기에 대해서 알아보겠습니다.
'Silverlight' 카테고리의 다른 글
| [엘리의 실버라이트 2.0] Plain XML 보내기 • 받기 (0) | 2008/09/06 |
|---|---|
| [엘리의 실버라이트 2.0] 스플래시 스크린 만들기 (0) | 2008/08/25 |
| [엘리의 실버라이트 2.0] Silverlight 입력 이벤트 핸들러 작성 (2) (0) | 2008/08/19 |
| [엘리의 실버라이트 2.0] Silverlight 입력 이벤트 핸들러 작성 (1) (2) | 2008/08/12 |
| [세티의 실버라이트] 15. 미디어 (0) | 2008/08/11 |
| [엘리의 실버라이트 2.0] Visual Studio의 개체 브라우저에 대해 알아보자. (0) | 2008/08/06 |
