C# WPF를 활용한 SW를 개발할 때,
프로그램의 디자인은 XAML 코딩을 통해 형성할 수 있다.
이 중 Window, Page, UserControl과 같은 가장 큰 개념을 제외하면
우리가 생성할 "창"을 원하는 구역으로 분할 할 수 있는 큰 개념이 Grid라고 생각한다.
(백문이 불여일견...)
우선 난 HomeView라는 메인뷰(메인 인터페이스)에 종속되는 UserControl을 생성하였다.
이때 코드적 관점에서
<UserControl x:Class="IPLProject.Views.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:IPLProject.Views"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
mc:Ignorable="d"
d:DesignHeight="600"
d:DesignWidth="1000">
위와 같이 UserControl의 기본 속성을 정의하게 되는데,
저 UserControl의 영역에 커서를 갖다댄 뒤 클릭하면
위 사진과 같이 생성한 UserControl 전체 영역이 선택된 선을 확인할 수 있게된다.
그리고 우리는 가장 먼저 (상황에 따라 다르지만 일반적으로) 저 선택된 전체 영역의
'좌측 상단엔 그룹 박스를 할당해야지'
'좌측 하단 남은 공간은 로그 뷰어를 생성해야지'
'우측은 옵션이나 PreView 인터페이스를..'
...
등등 생성된 UserControl에 어떤 컨트롤들을 배치할 지 간략적인 그림을 그려나가게 된다.
그리고 그에 대한 설계가 완료되면 위 사진과 같이 각 구역에 컨트롤을 배치할 Grid를 나눌 수 있게 되는 것이다.
우선 그리드는 어떤 한 공간을 어떤 방식의 Row와 Column으로 나눌 것인지를 정의하는 기능을 뜻하는데,
위 사진의 가장 큰 개념의 Grid는
<!--유저컨트롤 전체 나누기 (2*3)-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="120*" />
<RowDefinition Height="120*" />
<RowDefinition Height="210*" />
</Grid.RowDefinitions>
를 통해 정의한 것이다.
<Grid.ColumnDefinitions> : 그리드를 열로 나눔
ColumnDefinition Width="*" : 열로 나눈 그리드가 차지하는 영역비율. 저기서 star point로 2개의 칼럼 데피니션을 지정했다는 것은 1:1 비율로 열을 나누겠다는 의미이다.
<Grid.RowDefinitions> : 그리드를 행으로 나눔
RowDefinition Height="120*" : 행으로 나눈 그리드가 차지하는 영역비율 - 위 코드는 120:120:210 의 비율로 행을 나누겠다는 의미이다.
전체 그리드를 나누고 나서 프로그래밍을 진행하다보니 한가지 에러 사항이 생겼다.
Text Block이 예쁘게 수직+수평 정렬이 되지 않는 것이다.
(가정한 상황)
그렇다면 우리는 위의 Item ID, Production ID, 2개의 TextBox가
저 Label Data라는 그룹 박스 안에
4 공간을 차지함과 동시에
수직 수평 정렬이 되도록 디자인 해야되는데...
= 전체영역을 나눈 그리드 안에 또 그리드를 지정해야 되는 것이다.
당연하겠지만 안될리가 없다.
<Grid>
<!--유저컨트롤 전체 나누기 (2*3)-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="120*" />
<RowDefinition Height="120*" />
<RowDefinition Height="210*" />
</Grid.RowDefinitions>
<!--라벨 데이터 입력부 그리드-->
<Grid Grid.Row="0"
Name="labelDataGrid">
<!--라벨 데이터 그룹박스 설정-->
<GroupBox Header="Label Data"
Foreground="White"
FontWeight="Medium"
FontFamily="Montserrat">
<!--그룹박스 TextBlock|TextBox 나누기(2*2)-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--TextBlock1 위치 (1,0,0,0)-->
<Grid Grid.Column="0"
Grid.Row="0"
Name="labelDataTextBlock1Grid">
<TextBlock Text="Item ID"
Foreground="White"
FontSize="25"
FontWeight="Medium"
FontFamily="Montserrat"
TextAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="1,1,1,1" />
</Grid>
<!--TextBlock1 위치 (0,0,1,0)-->
<Grid Grid.Column="0"
Grid.Row="1"
Name="labelDataTextBlock2Grid">
<TextBlock Text="Production Date"
Foreground="White"
FontSize="25"
FontWeight="Medium"
FontFamily="Montserrat"
TextAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="1,1,1,1" />
</Grid>
<!--TextBlock1 위치 (0,1,0,0)-->
<Grid Grid.Column="2"
Grid.Row="0"
Name="labelDataTextBox1Grid">
<TextBox x:Name="textBoxID"
FontSize="25"
FontWeight="Medium"
FontFamily="Montserrat"
Background="Transparent"
Foreground="White"
CaretBrush="{StaticResource plainTextColor3}"
BorderBrush="{StaticResource plainTextColor3}"
BorderThickness="0,0,0,2"
Margin="1,1,1,1"
TextWrapping="Wrap"
Text="1111111111"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="225"
Height="40" />
</Grid>
<!--TextBlock1 위치 (0,0,0,1)-->
<Grid Grid.Column="2"
Grid.Row="1"
Name="labelDataTextBox2Grid">
<TextBox x:Name="textBoxWeek"
FontSize="25"
FontWeight="Medium"
FontFamily="Montserrat"
Background="Transparent"
Foreground="White"
CaretBrush="{StaticResource plainTextColor3}"
BorderBrush="{StaticResource plainTextColor3}"
BorderThickness="0,0,0,2"
Margin="1,1,1,1"
TextWrapping="Wrap"
Text="20230810"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="225"
Height="40" />
</Grid>
</Grid>
</GroupBox>
</Grid>
Grid Grid.Row="0"
: 그리드 행의 0번째(배열과 같이 0부터 시작이다.) 영역에 대한 정의. 즉, 위에서 2*3으로 나눈 메인 Grid (라고 칭하겠다.)의 0번째 행을 의미함.
Grid Grid.Column="0"
그리드 열의 0번째 영역에 대한 정의. 즉, 위에서 2*3으로 나눈 메인 Grid (라고 칭하겠다.)의 0번째 열을 의미함.
※ Grid.Column="0" Grid.Row="1" 과 같이 복합 적용이 가능함.
위 코드와 같이 가장 큰 범위의 메인 Grid
안에 다시 그룹박스를 2*2 범위의 그리드로 설정함으로써
(당연히 코드는 상당히 비효율적일 수 있다. 하지만 심미적 만족도를 위해 이정도는 감수할 필요가 있지않나...
마우스로 그냥 대충 설정할 수도 있지만, 개인적으로 Margin을 통해 지정한 것은 추후에 윈도우 크기를 변경하거나, 각 사용자의 화면 해상도 등의 변수로 인해 언제든 대참사가 일어날 수 있음을 명심하자. )
그룹 박스 안의 컨트롤들을 디자인적으로 아주 편-안하게 수직수평 중앙 정렬하도록 하였다.
추가적으로 위 코드엔 나오지 않지만
<!--라벨 미리보기 창 그리드, 그리드 분할-->
<Grid Grid.Column="0"
Grid.Row="1"
Grid.RowSpan="2"
Name="logViewGrid">
</Grid>
Grid.(Column)RowSpan 기능이 마지막으로 존재하는데,
Span이란 상위 Grid에서 지정한 영역을 포함(초과)하여 설정하고 싶을 때 사용한다.
위 Log Box처럼 나는 메인 Grid를 120:120:210로 나눴지만, 120:330으로 좌측 하단에 LogBox를 사용하고 싶다!
라고 한다면
0번째 열 + 1번째 행 + RowSpan=2
를 적용한 logViewGrid를 정의하면 되는 것이다.
(Margin은 Grid에만 적용되는 기능은 아니니 따로 설명하겠다. - 0,0,0,0 좌상우하 순서로 영역을 얼마나 들여쓸 것인가에 대해 정의함.)