본문 바로가기

Coding Note

[WPF] Layout


WPF에서는 윈도우의 layout을 잡는데 도움이 될만한 클래스들을 많이 만들어두었다. form 시절 정겹던 패널도 보이고, 새롭게 나온 container들도 보인다. 그런데 WPF의 layout container class들은 form시절의 그것과 조금 다른점이 있는데, 윈도우 사이즈 변화에 따른 유동적인 처리를 지원한다는 것이다.
 이번 글에선 이런 신기한 일을 해주는 Layout Container 들과 사용되는 형태들을 알아보자.

 들어가기 앞서 Layout이 무엇인가? 영영사전을 보면 이렇게 설명하고 있다.
             "The layout of a garden, building, or piece of writing is the way in which the parts of it are arranged"
그럼 WPF에서의 layout은? 바로 UI Control 들의 배치를 정하는일이 되겠다.
 이전의 hard-coded sizing은 동적인 폼 변화에 유동적으로 대응하기가 힘들었다. WPF의 Layout Container들은 '영역'에 대한 구분을 통해 이를 쉽게 가능하도록 해줄 것이다.

 하나 더 있다. WPF에서 layout container는 어떻게 구성되고, laying out이 어떻게 이루어지는지 그 Process 를 살펴보자. 
Layout Container : System.Windows.Controls.Panel class를 상속받아 구성된다. 즉, 모든 layout container control들은 pnel클래스의 주요 3가지 속성을 기본적으로 가지고 있다.
-Background : background의 brush속성
-Children : Panel 내에 위치하는 자식 엘리먼트의 리스트.
-IsItemsHost : Item에 대한 호스트이면 true.(기본 false)

Layout Process : WPF에서 laying out할 시에는 두 스테이지에 맞춰 layout 내의 control들을 위치시킨다.
 1. A measure stage : 자식 엘리먼트가 요구하는 사이즈에 맞게 스테이지를 측정한다.
 2. An arrange stage : 적당한 위치에 자식 엘리면트를 위치시킨다.
 [컨테이너 엘리먼트가 자식의 크기요구를 수용할 수 없으면, 자식 엘리먼트의 사이즈를 보이는 영역에 맞게 줄이기도한다.(이런 상황을 피하려고 min size를 정해둠)]

 뭐 이것들은 기본 바탕내용일 뿐이고, 사실 눈앞에 보이는 필요는 Container 자체이겠지. 아래에서 layout container control들에 대해 설명하였다. 하나하나 살펴보고 직접 해보면 별거없다.(근데 이걸 어떻게 만들었을까 생각하고, 뜯어보면 후덜덜이다..ㅋ..)

Layout Container Control의 종류
 -Canvas : 절대좌표를 통해서 크기를 정해버림. 주변 control과의 조화없이 그냥 무대뽀로 자리잡음. 윈도우 크기변경에 동적인 대응 그딴거 없다ㅋ

 -DockPanel : 자식 엘리먼트들이 서로 대항하도록 자리잡게됨. (주로 Attached DockPanel.Dock property로 위치를 정렬시킨다.)

 -Grid : 포토샵의 그리드와 비슷. 보이지않는(보이게 할수도 있고)선으로 영역을 row와 column으로 구분시킴

 -StackPanel : 스택처럼 먼저생성한 자식 엘리먼트가 정렬방향(Orientation property)대로 쌓임. 주로 큰 공간의 구역을 잡을 때 사용됨. 

 -WrapPanel : 아이템의 정렬을 Row의 관점에선 좌->우 로, Column의 관점에선 위->아래로 자동 정렬한다. 아마도 "윈도우 사이즈 변화에 따른 유동적인 변화" 를 가장 잘 나타내는 것 같지만,, 나는 잘 안쓴다.

 -UniformGrid : 가능한 영역을 자식엘리먼트의 수에 따라 적당한 갯수의 Cell로 분할시켜 모든 자식 엘리먼트가 같은 사이즈가 되도록 강제시킨다.(테이블을 만든다고 보면 되고, 잘 안쓰인다.)

 설명이야 눈으로 흘기겠지만, 사용하는 예는 직접 해보는게 몸에 금방 익는다. 자주 사용하는 control들에 대해서만 예제를 실어봤다.
1. Canvas : 절대좌표를 사용한 Layout방식 Lef, Top, Width, Height,를 통해 Layout한다. 먼저 선언한 Canvas가 가장 바닥에 위치하는 스택 구조이다. 절대좌표를 사용해 쉽게 Layout을 지정할 수 있지만, 부모객체의 크기변화에 동적으로 변화될 수 없다.(동적인 resizing을 구현해주면 되겠지만..)
 <Canvas Width="400" Height="300" Margin="0">
            <Canvas Canvas.Left="0" Canvas.Top="0" Height="100" Width="80" Background="Aqua"/>
            <Canvas Canvas.Left="60" Canvas.Top="60" Height="100" Width="100" Background="Silver" />
            <Canvas Height="100" Width="100" Canvas.Right="0" Canvas.Bottom="0" Background="BurlyWood" />
        </Canvas>

2. DockPanel : 패널 내의 컨트롤들은 Dock property를 attached property형식으로 지정함으로서 패널 내에서 위치를 지정할 수 있다. Dock property는 Top, Bottom, Left, Right의 값을 가지며 공간에서 지정된 위치로 정렬된다.
DockPanel의 중요한 특징은 Dock property를 통한 Control의 정렬은, Control이 DockPanel 태그 내에서 생성된 위치에 따라 달라진다는 점이다. 예를들어
 <DockPanel LastChildFill="True" >
            <Border DockPanel.Dock="Top" Background="SeaShell" Height="50">
                <TextBlock >first</TextBlock>
            </Border>
            <Border DockPanel.Dock="Top" Background="Azure" Height="50">
                <TextBlock>second</TextBlock>
            </Border>
            <Border DockPanel.Dock="Left" Background="DarkMagenta" Width="250">
                <TextBlock>third</TextBlock>
            </Border>
            <Border DockPanel.Dock="Right" Background="Fuchsia">
                <TextBlock>fourth</TextBlock>
            </Border>
        </DockPanel>
와 같이 작성한다면, first와 second가 모두 위로올라가있는 이상한 상황이 되는게 아니라, 맨 처음 생성된 first가 DockPanel의 맨 위로 올라가고, 그 다음 second가 남은 공간의 Top으로 올라가게된다. 마찬가지로 세번째로 생성된 third가 남은 DockPanel 공간의 왼쪽을 넓이 250pixel만큼 차지하며 DockPanel의 LastChildFill="True"속성으로 인해서 남은 공간을 전부 네번째 컨트롤인 fourth가 차지하게된다.

3. Grid : Layout을 조정하는데 가장 흔히 사용되는 Layout Container control로 세로, 가로선으로 영역을 분할하여 Row와 Column으로 Attached 된 Property로서 원하는 영역에 Control을 배치할 수 있다. 이 때 여러 영역을 엮어서 하나의 컨트롤이 사용하려 한다면 RowSpan이나 ColumnSpan으로 엮을 셀의 갯수를 지정할 수 있다.
 <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Background="Aquamarine" />
        <Border Grid.Column="0" Grid.Row="1" Background="Salmon" />
        <Border Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Background="DarkOrange" />
    </Grid>

그 외 Layout Control은 신기하긴 하지만, 별 내용이 없어서 넘어간다 ㅋ..

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

[WPF] User Dependency Property  (0) 2012.01.21
[WPF] Dependency Property  (0) 2012.01.21
[WPF] Properties  (2) 2012.01.20
[WPF] about XAML  (0) 2012.01.19
[WPF] 첫번째 프로그램  (0) 2012.01.16