본문 바로가기

Coding Note

[WPF] about XAML


이번 포스팅에선 WPF의 중요한 부분을 담당하는 XAML 에 대해 설명해보려고 한다.
발음은 재믈, 잼을, 즈믈, 엑새이에멜...   등 다양한데 개인적으론 재믈이 멋있다.

▷ about XAML
XAML은 저번에도 언급했듯, XML기반의 어플리케이션을 위한 확장된 마크업 언어이다. 특히나 윈도우의 표현기반(WPF)의 중요한 요소이기 때문에 XAML을 빼놓고는 WPF를 설명할 수가 없다.  그만큼 중요하단 소리이다. 그렇다면 XAML의 주요 역할에는 뭐가 있을까?

1. 우선 눈에보이는 역할은, 그래픽과 로직을 분할시켜 독립적으로 작업할 수 있게 해준다는 것이다.
XAML은 디자이너와 프로그래머의 분업을 원활하게 만들어줘서 더욱 이쁜 어플리케이션을 만들 수 있게 해준다. 그런데 디자인의 분리는 단순히 이쁘게만 하는게 목적의 전부가 아니다. 디자인이 분리된다면 수정 및 보완에 상당한 시간절약이 가능해지고, 이는 과 직결되는 중요한 요소이다. winapi나 MFC 중 내부 알고리즘이 아닌 ui쪽을 수정하려 할 때 부담 쓰나미를 경험해본 사람이라면 이런 XAML의 강점은 너무나도 고마운 것이리라..

2. 두번째로 XAML은 사용자 동적인 효과를 구현할 수 있게해준다.
일반적인 윈폼으로 제작된 윈도우의 경우, 가능은 하지만 동적인 효과의 구현은 매우 힘들었다. 특히나 디자이너의 창의적인 요구는 개발자에게 기존 컨트롤들을 뜯어고치길 요구했고, 이는 내부로직에만 힘써도 모자란 시간에 큰 타격이었다.
 하지만 XAML을 통해서 디자이너가 원하는만큼 다이나믹한 효과를 적용할 수 있게 되었고, 이는 어플리케이션의 사용자에게 더욱 친숙하게 다가갈 수 있는 계기가 되었다고해도 과언이 아니다.

 '사용자 동적인 효과' 에 추가적인 설명을 하자면, XAML이 HTML과 비슷한 태그형식이라는 점을 생각할 때 웹페이지를 떠올릴 수 있을것이다. 그리고 php등을 통한 동적인 웹페이지를 생각해보면 XAML을 통한 어플리케이션의 동적인 페이지화 또한 가능하다는 것을 생각해 볼 수 있다. 실제로 XAML은 페이지개념을 지원하고, 일반 어플리케이션임에도 불구하고 웹페이지와 같은 페이지구조의 어플리케이션을 만들 수 있다. 실로 놀랍지아니한가 하하..

아 그런데 중요한 사실은 WPF는 XAML을 무조건 필요로한게 아니라는 점이다. XAML없이 순수하게 WPF클래스들을 이용해서 어플리케이션을 구현할 수 있다. 하지만 콜라보레이션의 극대화를 위해 XAML은 중요한 사항이니 굳이 빼놓을 필요는 없어보인다.
(.. 라곤 말했지만, 사실 XAML없이 WPF클래스만을 이용해서 윈도우를 표현할 수 있는 능력은 꽤나 중요하다. 이 말은 WPF의 기반클래스를 깊게 이해하고 있어야 가능하기 때문에 진정 WPF마스터가 되려한다면, 필요한 사항이다.)


다른 역할들은 생각날때 설명하도록 하고, WPF에서 XAML사용의 키 포인트를 짚어보자.
[Key1] : Properties
[Key2] : Layout
[Key3] : Routed Events
[Key4] : Content Model

XAML 설명의 흐름이 이 키 포인트에 맞춰 흘러가기 때문에 공부중에도 이 흐름을 놓치지 않아야 쉽게 나아갈 수 있을것이다.

이번 글은 XAML에 대한 간략한 내용인 만큼 키포인트에 대한 설명은 다음글부터 차근차근 하기로 하고,,
기본적으로 XAML의 Syntax가 어떻게 구성되는지를 보도록 하자.

XAML은 계속 언급했듯 XML과 매우 흡사하다. XML을 알고있는사람이라면 문법자체는 큰 어려움 없이 익숙해 질 수 있을것이다.(XML을 모르는 사람이라면 W3C에서 XML에 관한 원문을 보거나 튜토리얼을 통해 먼저 익히길 권장한다.)

처음 프로젝트를 만들 시 자동생성되는 기본XAML코드를 통해 문법특징을 살펴보자.
<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="projectName.MainWindow"
    Title="MainWindow" Height="300" Width="400" >
  <Grid>
  </Grid>
</Window>

▷XAML Syntax Characteristic
우선 하나의 루트 엘리먼트가 꼭 있어야 한다. WPF에서의 XAML은 <Window> 로 시작을하고 </Window>로 끝을맺는다.
<Window>엘리먼트는 윈도우 전체에관한 속성과 폼이 로드될 때의 이벤트핸들루틴 등을 라우팅할 수 있다. 또한 xml스키마의 네임스페이스를 정의하는데, 이 두가지과 네임스페이스 선언은 꽤나 중요하니 잠시 후 보도록 하자. 
 <Window> 태그 안으로 <Grid>엘리먼트가 자리잡고있다. 사실 <Window>만 쓰고나면 그 아래내용은 마음대로이다. 하지만 레이아웃을 위해 <Grid>를 잡고있다.
 그 외 문법적 특징으론,,
♪ XAML의 Elements는 대.소문자에 민감하다 <Window>와 <WINDOW> 는 전혀다른 엘리먼트이니 주의해야한다.
♪ <와 >로 둘러싸인 속으로 해당 엘리먼트의 속성을 부여할 수 있다.
♪ 엘리먼트의 속성(Property)도 대.소문자를 구분한다.
♪ 속성의 값은 더블쿼터(" ")로 감싸져있다. (속성의 값은 대.소문자를 구분하지 않는다.)
♪ 속성의 값으로 < 와 같은 태그용 특수문자는 는 사용할 수 없다. XML처럼 아래와 같은 형태로 사용해야 한다.
    &lt;         <
    &gt;        >
    &amp;    &
    &apos;   '
    &quot;    "
이고 대부분 XML의 특징과 같다.

▷XAML Namespace
문법엔 큰 어려움이 없을것이라 생각하고, 네임스페이스의 임포트에 대해 살펴보자.
XML에서도 표준 엘리먼트를 정의한 네임스페이스를 임포트하고, 미리 정의된 엘리먼트로 태그를 작성할 수 있었다. 마찬가지로 XAML에서도 미리 정의된 클래스를 네임스페이스 임포트를 통해 사용할 수 있다.(정의된 클래스를 XAML문서 내에서 태그로 사용되면 엘리먼트이다.)
 그런데 XAML에서의 네임스페이스는 XML보다 더 중요한데, XAML파서가 문서를 파싱할 때 사용되는 네임스페이스가 임포트되어있지 않으면 문서에서 사용된 클래스가 어느곳에 속한 클래스인지, 어떻게 해석되어야 하는지 알 수가 없다. 때문에 사용하려는 클래스에대한 네임스페이스는 꼭 임포트 해줘야 한다.
 임포트방법은, xmlns 속성으로 값을주게된다.     xmlns:prefixName = "namespace" 의 형태로 하면 되고, 이 때 네임스페이스는 마소에서 미리 정의한 네임스페이스이거나 직접 만든 네임스페이스, 또는 어셈블리 등이 올 수 있다.
 위에서 보이는 네임스페이스는, "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 에서 WPF클래스에 대한 모든 내용과 UI 컨트롤에 관련된 내용을, "http://schemas.microsoftcom/winfx/2006/xaml" 에서 XAML파서가 문서를 어떻게 해석할지를 알려준다.

중요한 또한가지는 외부 네임스페이스나 내가 정의한 네임스페이스를 XAML문서상에서 사용하는것인데, 사용할 부모태그의 xmlns속성으로 정의한 네임스페이스를 선언해주고, 정의한 프리픽스를 통해 참조하면 된다.  형태는
                 xmlns:myns = "clr-namespace:MyNamespace"   와 같이 작성되며
                 myns:DefClass  와 같이 사용되게 된다.
(어셈블리의 경우 xmlns:prefix="assembly=asmName" 으로 작성되고, 세미콜론(;)으로 네임스페이스와 어셈블리 임포트를 동시에 해줄 수 있다.  xmlns:prefix="clr-namespace:Namespace;assembly=Asms" )

그런데 내가 정의한 네임스페이스 내의 클래스들은 WPF클래스들과 달리 생성자가 규격화되어있지 않다. 그래서 클래스의 속성을 줄 때 난감한 현상이 생기는데, 이 때 규격을 맞춰주거나 XML에선 불가능한 부분을 보완한 Markup Extension이란 방법을 통해서 가능하게 되었다. (이 내용은 다음글 에서 ㅎ..)

▷Code - Behind
about XAML이라곤 했지만, XAML만으론 이벤트에 대한 처리가 힘들다. 그래서 c#이나 VB.net을 통한 내부 로직을 만들게되는데, 이 때 코드를 code-behind나 숨김코드 라고 한다. 이 때 프리픽스 x로 선언된 네임스페이스의 Class라는 클래스를 통해서 code-behind를 알려주게된다. (프리픽스가 정의된 네임스페이스의 클래스참조는 prefix:classes  와 같은 형태로 참조된다.)
                <Window x:Class="projectName.MainWindow"  ... >    ...   </Window>
이렇게 선언된 Class는 파서에게 '이 XAML문서를 볼 때 이벤트라우팅은 projectName의 프로젝트안에 MainWindow.cs파일속에 있는 이벤트핸들러를 참고하여라...'   라고 알려주게된다.
(위에서 언급했듯 프리픽스 x의 네임스페이스는 파서에게 파싱에 관련된 내용을 알려준다고 했었다.  만약 x가 아닌 다른 프리픽스명을 갖는다면, 그 프리픽스로 Class 클래스를 참조해야 할 것이지만, x로 명명하는걸 규칙으로 삼고 있다고 한다.)

▷Naming
c# winform 에선 드래그 앤 드랍 방식으로 컨트롤을 만들면 자동으로 Name property를 적당히 초기화시킨다. 그리고 코드상에서 이 이름을 통해 컨트롤의 속성이나 메서드 또는 이벤트에 접근할 수 있었다. 그런데 XAML에서는 자동으로 Naming해주지 않는다. 대신 필요한 부분에만 이름을 두어 접근할 수 있게 했다.
 Naming은 어플리케이션의 동적인 형태를 구현하는데 조금 더 편하게 만들어주기도 한다. 이름이 지정된 클래스는 code-behind에서 그 이름으로 클래스에 접근이 가능하고, 내부 구현자는 이를 통해서 XAML만으론 하기 힘든 작업을 손쉽게 할 수 있기 때문인데, 더해서 같은 종류의 컨트롤들을 구분할 수 있기 때문에 상황에 맞게 사용할 수 있다.
 클래스의 naming은 ,
                        <Button x:Name="name"  ... />
와 같이 사용할 수 있고, code-behind에서 dot operation을 통해 관련된 멤버나 이벤트를 접근할 수 있다.

☆잠깐 쉬어가기 - [x:Name 과 Name의 차이]☆
 Name은 프리픽스 x로 정의된 네임스페이스 안에도 있고, WPF클래스의 속성으로도 있다.
두 개의 기능적인 차이는 없다. 하지만 애니메이션이나 스토리보드쪽의 일부 클래스는 Name속성을 갖지 않는다. 그러니 그냥 x:Name으로 사용하면 딱히 문제될점이 없고 편하다. 조금 찜찜하긴 하지만,,, 자세한 이야기를 알고싶으면 여기에서!

▷Event Routing
XAML에서 컨트롤의 이벤트를 처리하려면, 정의한 code-behind에서 event handler 루틴을 정의하고 라우팅을 해줘야한다.
라우팅은 XAML문서안에서 이벤트 라우팅하려는 클래스의 속성으로 이벤트명을 써주고, 그 값으로 앞서 정의한 루틴의 이름을 넣어주면 된다.
                 [XAML file]
                     <Button Click="button_click" />
                 
                 [XAML문서 내에서 지정된 Code-behind file]
                               ....
                      public void button_click(object s, RoutedEventArgs){
                                          //처리
                      }
음, Visual Studio에선 이벤트속성에 값을 입력하려 하면 <New Event Handler> 로 컨트롤 특성에 맞게 알아서 핸들러를 code-behind내에 만들어주니 함수 파라미터 형식이 익숙해지기 전까진 이런식으로 익혀야겠다.

쓰다보니 조금 길어졌는데 내용은 별거없다. 다음번 글을 통해서 속성을 주는 여러가지 방법에 대해 알아보고, 페이지기법이나 애니메이션기법등은 천천히 공부하자.

'Coding Note' 카테고리의 다른 글

[WPF] Layout  (2) 2012.01.20
[WPF] Properties  (2) 2012.01.20
[WPF] 첫번째 프로그램  (0) 2012.01.16
[WPF] WPF 시작하기  (1) 2012.01.16
[C++] 상속과 다형성  (0) 2011.12.20