웹에서 드래그 앤 드랍을 구현하기란 무척이나 힘들다. SilverLight의 경우는 이러한 문제를 깔끔(?)하게 해결해 준다.
마우스의 드래그 앤 드랍을 구현하기 위해서는 이전 포스트에서도 적었듯이 세가지의 마우스 이벤트를 필요로 한다. 여기서 다시금 적어본다.
MouseLeftButtonDown
드래그 가능한 요소를 클릭하는데 드래그 모드의 시작점이다.
MouseMove
마우스 클릭을 유지한 상태로 마우스를 이동시킨다.
이 때 오브젝트는 마우스의 포인트를 따라서 같이 움직이게 된다.
MouseLeftButtonUp
마우스 버튼을 놓았을 때, 즉 드래그 모드에서 해제된다.
여기의 3가지 이벤트와 자바스크립트 메소드 3개로 해결될 것 같은 느낌이 든다.
나머지 잡다한 것들은 잔머리만 잘 굴리면 해결된다. 예를 들면 두개의 Canvas가 있는데 A라는 캔버스에서 B라는 캔버스로 객체를 옮기고 싶다. 옮기고 나서 객체의 색을 변경시키는 것과 같은 요소들은 얼마든지 머리만 조금만 굴리면 충분히 구현이 가능한 것이다. 하지만 이러한 것을 구현하기 위해서 반드시 알아야 할 것이 있다.
바로 EventBubbling이라는 것이다. 드래그가 가능한 객체 이외의 오브젝트에서는 마우스 이벤트가 발생하지 않도록 하는 것이 중요하다. 즉 현재 드래그 하려는 객체에만 모든 마우스의 이벤트가 집중하도록 하는 것이다. 특히 드래그의 경우는 마우스를 클릭해서 오브젝트를 이동시키는데 마우스 이동 도중에 혹시 다른 오브젝트에 MouseMove이벤트가 있다면 어떻게 될까? 생각한 대로 처리가 되지 않을 것이다. 이러한 문제를 해결하는 것이 captureMouse라는 메소드이다.
captureMouse는 일반적으로 MouseLeftButtonDown이벤트에서 실행을 시킨다. 그리고 MouseMove이벤트가 발생하는 동안 드래그하려는 오브젝트에 모든 마우스 관련 이벤트를 집중시킨다.(특히 MouseMove). 따라서 다른 곳에서 MouseMove 이벤트가 있더라도 무시하고 현재 captureMouse가 실행되고 있는 오브젝트에만 집중할 수 있게끔 해 주는 역할을 하는 것이다.
그럼 captureMouse를 해제하는 기능은? releaseMouseCapture()라는 메소드 이다. 이 메소드는 captureMouse를 실행시킬 때와는 반대로 MouseLeftButtonUp이벤트에서 실행을 시킨다. 즉 드래그가 끝나는 시점이 마우스의 버튼을 놓는 시점이 되기 때문이다.
아래의 예는 captureMouse와 releaseMouseCapture에 대해서 간략하게 예를 들고 있다.
이 예제는 드래그 앤 드랍에 대한 예제는 아니지만 captureMouse와 releaseMouseCapture를 이해하는데 많은 도움을 줄 것이다.
이 샘플은 MS의 도움말을 참조했다.
XAML파일
<Canvas
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="180" Width="300"
Background="PowderBlue">
<Rectangle
x:Name="Green"
MouseMove=onMouseMove"
MouseLeftButtonDown=onLeftButtonDown"
MouseLeftButtonUp=onLeftButtonUp"
Width="100" Height="100"
Fill="Green" />
<!-- The MouseMove event handler function is shared with the first rectangle -->
<Rectangle
x:Name="Red"
MouseMove=onMouseMove"
Canvas.Left="120"
Width="100" Height="100"
Fill="Maroon" />
<TextBlock
x:Name="statusTextBlock"
FontSize="18"
Canvas.Top="120" />
</Canvas>
자바스크립트 파일
// Display the current mouse position for the Rectangle object.
function onMouseMove(sender, mouseEventArgs)
{
var msg = "x:y = " + mouseEventArgs.getPosition(null).x + ", " + mouseEventArgs.getPosition(null).y;
sender.findName("statusTextBlock").Text = sender.Name + ": " + msg;
}
// Enable mouse capture when the mouse is depressed over the green Rectangle object.
function onLeftButtonDown(greenRect, mouseEventArgs)
{
greenRect.captureMouse();
}
// Disable mouse capture when the mouse is released over the green Rectangle object.
function onLeftButtonUp(greenRect, mouseEventArgs)
{
greenRect.releaseMouseCapture();
}
마우스를 녹색 사각형에서 클릭을 하기 전까지는 녹색 사각형에서 마우스를 이동시킬 경우 아래쪽 TextBlock에 Green과 함께 좌표가 나타나고 붉은 색 사각형에서 마우스를 동시킬 경우에는 Red라는 글자와 함께 좌표가 나타난다.
자 이제 녹색 사각형에서 마우스를 클릭한 상태로 붉은색 사각형으로 이동해 보자. TextBlock에는 어떤 현상이 발생하는가? Red라는 글자가 아니라 Green이라는 글자가 나타날 것이다. 즉, MouseMove에 대한 이벤트를 녹색 사각형 오브젝트가 모두 흡수(?)하고 있다는 뜻이다.
여기서 또 다른 의문점이 생겨난다. 현재 두개의 사각형을 포함하고 있는 부모 객체(Canvas)에 MouseMove이벤트를 구현할 경우 어떻게 될까? 그리고 오브젝트들이 계층적으로 존재할 경우 Event들은 어떻게 처리가 될까?
이러한 모든 부분을 다 해결하고 나서 드래그 앤 드랍에 대해서 본격적으로 구현을 해 볼 것이다. (드래그 앤 드랍에 대해서 그 결과만 보고 싶으면 얼마든지 구현이 가능하지만 근본적인 오브젝트와의 관계를 정확하게 이해야지만 실무에서 발생하는 문제들을 해결할 수가 있다.)
참고도서 : Essential SilverLight (O'REILLY), SilverLight 1.0 - Development with JavaScript.chm
'SilverLight' 카테고리의 다른 글
키보드 이벤트 탐색記 (0) | 2007.12.22 |
---|---|
마우스 Drag and Drop 탐색記 (2편) (0) | 2007.12.20 |
마우스!~ 이벤트 탐색記 (2편) (0) | 2007.12.19 |
마우스!~ 이벤트 탐색記 (1편) (0) | 2007.12.18 |
실버라이트가 지원하는 이벤트 처리기 (0) | 2007.12.18 |