최근들어 WPF를 이용해 CubeUI를 구현하는 방법에 대해 문의하시는 분들이 많아 이번시간에는 Cube UI를 WPF의 ListBox에 적용하여 이를 구현는 방법에 대해 소개해 드리고자 합니다..!! 아래는 구현 완료 동영상 입니다.
동영상만 봐서는 저게 뭐에다가 쓰이는 물건인지.. 감이 안잡히시죠?? (제목을 보셨다면 이해 하셨을수도.. ㅎㅎ) 이번시간에 구현할 내용은 WPF3D를 이용해 기존의 Listbox를 Cube모양으로 만들어 활용하는 방법에 대해 소개해 드리겠습니다. 먼저 구조에대해 설명을 드리겠습니다. (소스코드를 다운로드 받으셔서 확인해 가시면서 보시면 이해가 빠를것 같습니다!)
프로젝트를 열어보면 위 샘플에 사용된 이미지 몇장과 Cube3D.xaml, CubeListBox.xaml이 있습니다.
Cube3D.xaml은 Cube UI이기 때문에 Cube 모양을 정의 하는 Geometry가 포함된 ModelVisual3D객체 입니다. Cube3D에는 Front, Back, Left, Right, Top, Bottom이라 이름의 Property가 존재하는데요, 이는 Cube의 각각 면에 해당하는 합니다.
그리고 OffsetX, OffsetY, OffsetZ ... RotationZ 등은 제가 WPF를 이용해서 3D를 구현할때 자주사용하는 코드로 간단하게 Offset, Scale, Rotation을 적용하기 위한 코드입니다. 이부분은 다음에 더 자세히 다루도록 하겠습니다.
그다음 CubeListBox입니다. CubeListBox는 위에서 말씀드린 Cube3D를 템플릿에 활용하여 구현된 ListBox입니다. Template부분 코드를 보면 아래와 같습니다.
Viewport3D를 이용해 WPF3D를 사용하기 위한 Viewport를 생성하고 적당한 카메라와 조명의 위치를 잡은 뒤 위에서 말씀드렸던Cube3D객체를 추가합니다. 그리고 각면에 SelectedItem, PrevItem, NextItem등을 Binding하게되는데요.
여기서 Front에 SelectedItem을 Left에 PrevItem을, Right에 NextItem을 Binding하는 이유는 잠시후에 설명하도록 하겠습니다.
(SelectedItem은 사용자가 현재 ListBox에서 선택한 객체를 보여주고, PrevItem는 이전 NextItem은 다음 객체를 의미합니다.)
PrevItem과 NextItem은 Listbox에 기본적으로 정의된 Property가 아니기 때문에 새로 Dependency Property로 정의 하고, SelectedIndex가 변경되었을때 아래와 같은 내용으로 PrevItem과, NextItem에 값을 할당 해줍니다.
ListBox에 추가된 객체의 갯수보다 Nextndex가 클경우 Index를 0으로 설정하여 순환구조로 작성했으며 PrevIndex가 0보다 작을경우 마지막 항목의 Index를 지정하여 마찬가지로 순환구조를 가지도록 했습니다.
이렇게 하면 Cube상에 현재 선택된 객체는 Front에 다음 객체는 Right에 이전객체는 Left에 위치하게 됩니다. 이제 마우스 조작을 통해 큐브를 회전시키는 부분을 구현할 건데요...해당코드는 아래와 같습니다.
Cube를 회전 한다고해서 실제 ListBox의 SelectedIndex가 변경되는것이 아니기 때문에 회전 Animation이 완료되면 회전 방향에 따라 Index를 증가 또는 감소 시켜줍니다.
이렇게하면 Front에는 현재 선택된 객체가, Left에는 이전, Right에는 다음 객체가 보여지게 되는데요. 회전을 하게되면 Cube자체의 Front, Left, Right 면의 위치가 변하게 되어 뜻하지 않은 결과를 발생시킵니다. 이를 위해 Cube의 회전이 모두 끝나면 Animation을 제거하여 큐브가 회전하지 않은 상태가 되도록 합니다.
이렇게 구현된 CubeListBox는 아래와 같이 일반적인 ListBox와 같은 방식으로 사용하실 수 있습니다.
이상으로 이번 포스팅을 마치며 기타 질문이나 문의 포스팅 요청은 이메일이나 리플로 남겨제요 ^^
아래는 이번 시간에 작업한 내용의 전체 소스코드입니다.

WPFCubeUISample.zip
