본문 바로가기

프로그래밍언어/WPF

WPF 레이아웃

레이아웃: Panel 요소의 Children 컬렉션에 속한 멤버를 측정 및 정렬한 다음 화면에 그리는 프로세스를 말한다
WPF는 사용자 인터페이스의 레이아웃을 제어하기 위해 강력하고 유연한 여러가지 컨트롤들을 제공한다

그런 컨트롤들을 통칭해 패널(Panel), 또는 컨테이너 컨트롤 이라 할 수 있으며, 패널이란 자신이 소유한 요소들을 정렬하는 일을 수행하는 특수한 목적을 가진 사용자 인터페이스 요소이다

  • Canvas

Canvas는 가장 단순한 패널이다 모눈종이라고 생각하면 된다
기본 height 및 width 속성은 0이지만, 자식 요소의 크기를 자동으로 지정하는 요소의 자식일 때는 예외이다
자식요소는 크기가 조정되지 않으며 지정된 좌표에 배치되기만 한다
Canvas 크기가 달라지더라도 Canvas 안의 요소의 크기는 변하지 않는다

<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas Name="canvas1">
<TextBlock Canvas.Left="50" Canvas.Top="30" Height="21" Name="textBlock1" Width="120" Text="Sunflower" />
<Button Canvas.Left="156" Canvas.Top="26.48" Height="23" Name="button1" Width="75">Click</Button>
<Image Canvas.Left="39" Canvas.Top="79" Height="150" Name="image1" Stretch="Fill" Width="200" Source="/WpfApplication8;component/a.jpg" />
</Canvas>
</Window>

Canvas를 사용할 때는 고정된 레이아웃, 고정된 이미지를 나타낼 때 사용된다

  • DockPanel

화면에서 DockPanel 자식요소 위치를 Dock 속성 및 DockPanel 아래에서 이러한 자식 요소의 상대적인 순서에 따라 결정 한다
따라서 속성 값이 같은 여러 자식 요소가 DockPanel 아래에서 이러한 자식의 순서에 따라 화면에 서로 다르게 배치될 수 있다
자식 요소를 순서대로 반복하면서 여유 공간에 따라 각 요소를 배치하므로 자식의 순서가 위치에 영향을 준다

<Window x:Class="WpfApplication8.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="380" Width="499">
<DockPanel Name="dockpanel1" >
<Border DockPanel.Dock="Top" Height="25" Background="LightBlue" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="Dock = top"/>
</Border>
<Border DockPanel.Dock="Top" Height="25" Background="LightBlue" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="Dock = top"/>
</Border>

<Border DockPanel.Dock="Left" Width="100" Background="PaleGreen" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="Dock=left" />
</Border>
<Border Background="White" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="this content will fill the remaining space" />
</Border>
<Border DockPanel.Dock="Bottom" Background="Yellow" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="Dock=Bottom"></TextBlock>
</Border>
</DockPanel>
</Window>

노란색의 border를 중간으로 순서를 변경하면...

Dockpanel은 기본적으로 마지막 자식 요소를 할당하지 않은 나머지 영역을 채운다 이 동작을 방지 하려면 DockPanel의 LastChildFill="False"로 설정

  • Grid

Column과 Row를 나누고 Column과 Row 번호를 사용해 객체의 위치를 지정 할 수 있다
만약 한 개 이상의 Column이나 Row를 사용하고자 할 경우, ColumSpan 속성이나 RowSpan 속성을 상용하여 Column 과 Row를 병합하여 사용할 수 있다
ColumnDefinition와 RowDefinition를 사용하여 Grid를 나눌 수 있으며 Star, Auto, Absolute 방식으로 크기를 지정 가능하다

-Grid의 유연성: 2행 2열을 만들고, 처음 크기값을 주고나서 '1*' 라고 하면 나머지 영역이 할당된다

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>

<Button Grid.Row="0" Grid.Column="0" MinWidth="0">one</Button>
<Button Grid.Row="0" Grid.Column="1" MinWidth="0">two</Button>
<Button Grid.Row="1" Grid.Column="0" MinWidth="0">three</Button>
<Button Grid.Row="1" Grid.Column="1" MinWidth="0">four</Button>
</Grid>

- 각 행의 크기값을 비율로 정할 수 있음 '2*' , '1*'

Grid 크기 정보 공유

<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<Button Grid.Row="0">one</Button>
<Button Grid.Row="1">two</Button>
<Button Grid.Row="2">three(which is longer...)</Button>
<Button Grid.Row="3">four</Button>
</Grid>

행의 전체 같이 크기를 공유를 할려면 IsSharedSizeScope, SharedSizeGroup 두개의 설정을 해줘야 함

<Grid IsSharedSizeScope='true'>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="a" />
<ColumnDefinition Width="Auto" SharedSizeGroup="a" />
</Grid.ColumnDefinitions>

<Button Grid.Row="0" Grid.Column="0">one..........................................</Button>
<Button Grid.Row="0" Grid.Column="1">two</Button>
<Button Grid.Row="1" Grid.Column="0">three</Button>
<Button Grid.Row="1" Grid.Column="1">four</Button>
</Grid>

<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True" Height="390" Width="1079">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="a" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<Button Grid.Row="0" Grid.Column='0'>one..........................</Button>
<Button Grid.Row="0" Grid.Column='1'>thhwhhhhho</Button>
<Button Grid.Row="1" Grid.Column='0'>threemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm</Button>
<Button Grid.Row="1" Grid.Column='1'>four</Button>
</Grid>

<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="a" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0">a..........mmmmmmmmmmmmmmmmmmmmmmmmmmmm...........</Button>
<Button Grid.Row="0" Grid.Column="1">b</Button>
<Button Grid.Row="1" Grid.Column="0">c</Button>
<Button Grid.Row="1" Grid.Column="1">mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmd</Button>
</Grid>
</Border>
</StackPanel>

  • Stackpanel

자식요소를 행이나 열로 나열하는데 매우 간단한 컨트롤
StackPanel에 정의된 속성을 사용하여 세로로 흐르거나 가로로 흐를 수 있다
tackPanel의 기본 스택방향은 수직으로 StackPanel의 흐름을 제어하려면 Orientation속성을 사용하여 Orientation="Horizontal" 또는 Orientation="Vertical"로 설정한다

<Grid>
<StackPanel Name="stackpanel1" HorizontalAlignment="Left" Width="78" Orientation="Vertical" Height="117" VerticalAlignment="Top">
<Button Height="23" Name="button1" Width="75">버튼1</Button>
<Button Height="23" Name="button2" Width="75">버튼2</Button>
<Button Height="23" Name="button3" Width="75">버튼3</Button>
<Button Height="23" Name="button4" Width="75">버튼4</Button>
<Button Height="23" Name="button5" Width="75">버튼5</Button>
</StackPanel>
<StackPanel Name="stackpanel2" Orientation="Horizontal" Margin="95,33,0,75" HorizontalAlignment="Left" Width="251">
<Rectangle Height="50" Name="rectangle1" Stroke="Black" Width="50" Fill="Red" />
<Rectangle Height="50" Name="rectangle2" Stroke="Black" Width="50" Fill="Yellow" />
<Rectangle Height="50" Name="rectangle3" Stroke="Black" Width="50" Fill="Black" />
<Rectangle Height="50" Name="rectangle4" Stroke="Black" Width="50" Fill="Green" />
<Rectangle Height="50" Name="rectangle5" Stroke="Black" Width="50" Fill="Blue" />
</StackPanel>
</Grid>

  • WrapPanel

WrapPanel의 사이즈보다 그 안의 자식요소들의 크기가 작을 때는 Stackpanel과 같은 역할을 하지만 자식요소들의 크기가 더 크게 되면 wrappanel의 크기를 넘어선 자식요소를 다음 줄에 배치하는 특성을 가지고 있다
마치 문서를 작성할 때 한 줄로 쓰여지다가 글자가 한 줄의 크기를 넘어서면 다음 줄로 내려가 쓰여지는 방식과 같다

<WrapPanel Name="wrappanel1" VerticalAlignment="Top">
<Rectangle Height="50" Name="rectangle1" Stroke="Black" Width="50" Fill="Red" />
<Rectangle Height="50" Name="rectangle2" Stroke="Black" Width="50" Fill="Orange" />
<Rectangle Height="50" Name="rectangle3" Stroke="Black" Width="50" Fill="Yellow" />
<Rectangle Height="50" Name="rectangle4" Stroke="Black" Width="50" Fill="Green" />
<Rectangle Height="50" Name="rectangle5" Stroke="Black" Width="50" Fill="Blue" />
<Rectangle Height="50" Name="rectangle6" Stroke="Black" Width="50" Fill="Navy" />
<Rectangle Height="50" Name="rectangle7" Stroke="Black" Width="50" Fill="Purple" />
</WrapPanel>


기본적인 레이아웃 속성들

  • ActualHeight, ActualWidth, Height, Width

요소의 크기에 관련된 속성들

<Grid>
<ComboBox Name="comboBox1" Margin="125, 0, 125, 240">
<ComboBoxItem Content="sample" />
<ComboBoxItem Content="sample" />
<ComboBoxItem Content="sample" />
</ComboBox>
<Label Margin="21,0,20,133" Name="label1" Height="28" VerticalAlignment="Bottom" />
<Label Height="28" Margin="21,0,20,99" Name="label2" VerticalAlignment="Bottom" />
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,20,38" Name="button1" VerticalAlignment="Bottom" Width="91" Click="button1_click">사이즈 확인</Button>
</Grid>

private void button1_click(object sender, RoutedEventArgs e)
{
label1.Content = string.Format("ActualWidth:{0}, Width: {1}", comboBox1.ActualWidth.ToString(), comboBox1.Width.ToString());
label2.Content = string.Format("ActualHeight:{0}, Width: {1}", comboBox1.ActualHeight.ToString(), comboBox1.Height.ToString());
}

  • MaxHeight, MaxWidth, MinHeight, MinWidth

고정된 사이즈보다 어느 정도 사용자 UI를 고려해 요소크기의 초소한, 최대한을 정해 주는 것이다
그러면 그 사이에 있는 동안은 컨트롤의 사이즈는 자동으로 변하게 되며 지정한 최소, 최대 사이즈 범위를 벗어났을 경우에 요소의 크기는 더 이상 줄어들거나, 커지지 않을 것이다

  • FlowDirection

텍스트 및 기타 UI 요소의 콘텐츠의 흐름 방향을 지정하거나 설정할 때 기본적으로 system locale을 따른다
lefttoright - 콘텐츠가 왼쪽에서 오른쪽으로 흐름을 나타낸다
righttoleft - 콘텐츠가 오른쪽에서 왼쪽으로 흐름을 나타낸다

<FlowDocument>
<Paragraph FlowDirection="LeftToRight">
this paragraph will flow from left to right
</Paragraph>
</FlowDocument>

Paragraph par = new Paragraph(new Run("this paragraph will flow from left to right"));
par.FlowDirection = FlowDirection.LeftToRight;

  • HorizontalAlignment, VerticalAlignment

부모요소의 공간에서 어떻게 정렬 할 것인가를 조정할 때 사용하는 속성

<Button x:Name="button1" Content="button" HorizontalAlignment="Left" />
<Button x:Name="button2" Content="button" VerticalAlignment="Center" />

button1.HorizontalAlignment = HorizontalAlignment.Left;
button2.VerticalAlignment = VerticalAlignment.Center;


  • Margin, Padding

Margin은 레이아웃에서 요소의 주변에 남겨져야 할 공간을 결정할 때 사용한다

Margin 속성의 설정은 하나의 숫자, 짝을 이룬 2개의 숫자,, 또는 4개의 숫자를 나열하여 사용가능하다

<button x:name = "button1" margin="10" /> - 1,2,3,4 설정 값이 모두 10으로 설정
<button x:name = "button1" margin="0,10" /> -1,3 설정 값은 0 2,4 설정값은 10
<button x:name = "button1" margin="0,10,5,10" />- 차례대로 1,2,3,4 값이 설정된다

Padding은 Margin과 반대되는 경우라고 생각하면 된다
요소의 경계와 내부 콘텐츠 사이의 여백을 지정하기 위한 것이다

  • IsEnabled, Visibility

IsEnabled는 UIElement의 멤버로 UI에서 요소를 사용할 지의 여부를 결정하는데 사용된다
UIElement는 WPF요소 및 기본 표시 특성을 기반으로 빌드 되는 WPF 핵심 수준 구현에 사용되는 기본 클래스 이다

예를들어 영화좌석 예매를 하는데 화면에 좌석이 배치 되어있고, 그 좌석을 클릭해서 내가 예약하고자 하는 좌석을 결정한다 그런데 이미 예약 되어 있는 좌석은 다른 사람이 선택을 할 수 없을때 IsEnabled를 사용하는 것

IsEnabled는 True, false 로 설정 하며 false로 설정 되어 있다면 화면에 요소의 모양은 나타나는데 사용을 할 수 없다 이 것을 '비활성화' 라고 한다

visibility속성은 요소가 화면에 보여질지 보여지지 않은지를 결정하는 속성이다
visibility의 멤버로는 collapsed, hidden, visible이 있는데 collapsed와 hidden은 둘다 화면에 나타나지 않는다 하지만 차이점이 있다

<StackPanel Width="280" Background="Red" Name="stackpanel1" Height="50">
<Button Height="23" Name="button1" Width="75" Visibility="Hidden">확인 1</Button>
<Button Height="23" Name="button2" Width="75">확인 2</Button>
</StackPanel>

두번째가 visibility가 collapsed로 설정

collapsed는 width나 height 값이 0이므로 화면에 그려지지 않고, hidden은 width, height의 값을 다 가지고 있어 레이아웃에서 자기 자리를 차지하고 있지만 단지 눈에만 보이지 않는 것이다

  • layouttransform, render transform

해당 요소에 대한 크기(scaling), 회전(rotation)등을 변형시킬 때 사용하는 속성

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>

<Button Grid.Row="0">버튼 1</Button>

<Button Height="30" Grid.Row="1">
<TextBlock>
<TextBlock.RenderTransform>
<RotateTransform Angle="180" CenterX="20" CenterY="10" /> - Angle은 회전하는 각의 값을 설정하는 멤버로 설정하는 값에 따라 시계방향으로 각이 변경되게 된다
CenterX,y 라는 멤버는 회전 중심점으로부터의 x,y 좌표를 나타낸다
</TextBlock.RenderTransform>
버튼2
</TextBlock>
</Button>

<Button Grid.Row="2">
<TextBlock>
<TextBlock.LayoutTransform> - 레이아웃 요소에 영향을 줌
<ScaleTransform ScaleX="3" ScaleY="4" />- 크기를 변경할 때 사용할 수 있는 것이고 x,y 속성을 사용하여 지정한 배율로 요소의 크기를 조정 가능
예를들면 x값으로 1.5를 지정하면 요소 너비가 원래 너비의 150%로 늘려지고, y 값으로 0.5로 지정하면 요소 높이가 50%까지 줄어든다
</TextBlock.LayoutTransform>
버튼3
</TextBlock>
</Button>

<Button Grid.Row="3">
<TextBlock>
<TextBlock.RenderTransform>- 레이아웃 크기 또는 렌더링 크기 정보가 다시 생성되지는 않는다
<ScaleTransform ScaleX="3" ScaleY="3"></ScaleTransform>
</TextBlock.RenderTransform>
버튼4
</TextBlock>
</Button>
</Grid>

  • Panel.ZIndex

ZIndex는 평면에서 이 요소가 표시되는 순서를 설정하는 것이다
이 속성을 사용하는데 설정된 순서에 다라 제일 아래에 보이게 할 수 있고, 제일 위에 보일수도 있다

<Button Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="75">button1</Button>
<Button Height="23" HorizontalAlignment="Left" Margin="25,25,0,0" Name="button2" VerticalAlignment="Top" Width="75">button1</Button>
<Button Height="23" HorizontalAlignment="Left" Margin="40,40,0,0" Name="button3" VerticalAlignment="Top" Width="75">button1</Button>
<Button Panel.ZIndex="3" Height="23" HorizontalAlignment="Left" Margin="10,110,0,0" Name="button4" VerticalAlignment="Top" Width="75">button4</Button>
<Button Panel.ZIndex="2" Height="23" HorizontalAlignment="Left" Margin="25,125,0,0" Name="button5" VerticalAlignment="Top" Width="75">button5</Button>
<Button Panel.ZIndex="1" Height="23" HorizontalAlignment="Left" Margin="40,140,0,0" Name="button6" VerticalAlignment="Top" Width="75">button6</Button>


출처: http://ratmsma.tistory.com/entry/WPFDockPanel
http://dotnetmvp.tistory.com/28


'프로그래밍언어 > WPF' 카테고리의 다른 글

WPF 컨트롤 템플릿  (0) 2011.07.07
WPF 데이터 바인딩  (0) 2011.07.04
WPF(기본적인 개념,아키텍쳐)[XAML이란 무었인가  (0) 2011.06.29
Lan3 WPF Study –step1  (0) 2011.03.31
Hour 6 Introducing Data Binding  (0) 2011.03.24