.NET MAUI - XAML Grid 의 View(Control) 정렬

2022. 7. 13. 00:00MAUI

반응형

그리드는 행과 열로 구성된 레이아웃 패널이다.

다음 그림은 그리드의 개념적 보기를 보여준다.

 

행과 열 지정하기

그리드를 생성할 때 각 행과 열을 개별적으로 정의할 수 있다.

이 시스템을 사용하면 각 행의 높이와 각 열의 너비를 완전히 제어할 수 있다. 

모든 그리드에는 그리드의 모양을 정의하는 RowDefinition 및 ColumnDefinition 개체의 컬렉션이 있다. 

이러한 컬렉션을 각각 UI의 행 또는 열을 나타내는 RowDefinition 및 ColumnDefinition의 인스턴스로 채운다.

다음은 RowDefinition 및 ColumnDefinition에 대한 클래스 정의를 보여주는 두 개의 코드다.

public sealed class RowDefinition : ...
{
    ...
    public GridLength Height { get; set; }
}

public sealed class ColumnDefinition : ...
{
    ...
    public GridLength Width { get; set; }
}

RowDefinition에는 Height라는 속성이 있고 ColumnDefinition에는 Width라는 속성이 있다. 

이러한 속성을 사용하여 행의 높이와 열의 너비를 설정한다.

 

Grid 에서 width 및 height 의 형식은 GridLength 이다. 

이 형식은 아래와 같이 정의되어 있다.. 

public struct GridLength
{
    ...
    public GridUnitType GridUnitType { get; }
    public double Value { get; }
}

GridUnitType 은 다음의 3가지 값이 될 수 있다.

  • Absolute
  • Auto
  • Star 

 

Absolute

: 행 또는 열의 크기가 고정되도록 지정

C#

var row = new RowDefinition() { Height = new GridLength(100) };

Xaml

<RowDefinition Height="100" />

 

Auto

: Child view (Control) 에 맞게 행 또는 열의 크기를 자동으로 조정

모든 하위 View(Control) 를 찾아 가장 큰 View 의 크기에 행 또는 열 을 맞춘다.

C#

var row = new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) };

XAML

<RowDefinition Height="Auto" />

 

Star

: 비례 크기를 제공

 

사용 가능한 공간 결정

: 그리드는 별 크기 조정을 사용하지 않는 모든 행을 스캔한다.

모든 행의 높이를 더하고 그리드 자체의 높이에서 합계를 뺀다. 

이 계산은 모든 별 크기 행에 사용할 수 있는 공간의 양을 제공한다.

 

사용 가능한 공간 나누기

: 그리드는 각 행의 값 설정에 따라 모든 별 크기 행 사이에서 사용 가능한 공간을 나눈다. 

Value 속성을 별 크기로 정의된 모든 행 간의 비율을 결정하는 배수로 생각하자. 

예를 들어 별 크기의 행이 두 개 있고 둘 다 배수가 1인 경우 사용 가능한 공간은 둘 사이에 균등하다.

그러나 그 중 하나의 값이 2이면 다른 것보다 두 배의 공간을 갖게 된다.

 

어떤 grid 에 row 가 5 개 있고

5 개 의 모든 Height 를 합하면  20*  가 된다고 가정하자

 

첫번째 row 의 Height 가 5* 였다면 이것은 전체 공간에서 25% 의 높이를 갖게 된다. 

이런식으로 계산한다고 생각하면 된다. 

 

C#

var row = new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) };

XAML

<RowDefinition Height="2*" />

 

아래와 같은 코드가 있다고 가정해 보자

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="1*" />
        <RowDefinition Height="2*" />
    </Grid.RowDefinitions>
    ...
</Grid>

첫 번째 행의 높이는 100 단위로 고정된다. 

두 번째 행은 일반적으로 행에서 가장 높은 뷰의 높이를 갖는다. 

세 번째와 네 번째 행은 별 크기 조정을 사용한다. 

즉, 남은 사용 가능한 공간을 가져와 값 배수에 따라 비례적으로 나눈다. 

세 번째 행은 1*이고 네 번째 행은 2*이므로 네 번째 행은 세 번째 행 높이의 두 배가 된다.

 

위 코드를 간단하게 만들어 보자

<Grid RowDefinitions="100, Auto, 1*, 2*">
    ...
</Grid>

 

Grid 에 View(Control) 추가 하기

Grid 에 View 를 추가 하려면 행 번호와 열 번호를 조합하여 Cell 을 식별해야 한다. 

 

행과 열 Numbering 

행과 열의 번호는 0부터 시작한다. 시작점은 왼쪽 상단 모서리이다. 

다음은 4개의 행과 2개의 열이 있는 그리드의 번호 매기기를 보여주는 그림이다.

 

 

아래와 같이 Grid.Row 및 Grid.Column 을 통해 View 과 위치해야 하는 행과 열을 지정 할 수 있다. 

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" BackgroundColor="Navy" />
    
</Grid>

 

하나 이상의 row 와 column 에 View 를 추가 하려는 경우

GridRowSpan  또는 Grid.ColumnSpan 을 이용한다.

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" BackgroundColor="Navy" />
    
</Grid>

 

예제

Grid/MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.Grid.MainPage"
             Title="MainPage">
    <VerticalStackLayout>

        <Label Text="Bill" />
        <Entry x:Name="billInput" Placeholder="Enter Amount" Keyboard="Numeric" />

        <Label Text="Tip"   />
        <Label x:Name="tipOutput" Text="0.00" />

        <Label Text="Total" />
        <Label x:Name="totalOutput" Text="0.00" />

        <Label Text="Tip Percentage" />
        <Label x:Name="tipPercent" Text="15%" />
        <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" />

        <Button Text="15%" Clicked="OnNormalTip" />
        <Button Text="20%" Clicked="OnGenerousTip" />

        <Button x:Name="roundDown" Text="Round Down" />
        <Button x:Name="roundUp"   Text="Round Up" />

    </VerticalStackLayout>
</ContentPage>

Grid/MainPage.xaml.cs

namespace MauiApp1.Xaml.Grid;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
        billInput.TextChanged += (s, e) => CalculateTip(false, false);
        roundDown.Clicked += (s, e) => CalculateTip(false, true);
        roundUp.Clicked += (s, e) => CalculateTip(true, false);

        tipPercentSlider.ValueChanged += (s, e) =>
        {
            double pct = Math.Round(e.NewValue);
            tipPercent.Text = pct + "%";
            CalculateTip(false, false);
        };
    }

    void CalculateTip(bool roundUp, bool roundDown)
    {
        double t;
        if (Double.TryParse(billInput.Text, out t) && t > 0)
        {
            double pct = Math.Round(tipPercentSlider.Value);
            double tip = Math.Round(t * (pct / 100.0), 2);

            double final = t + tip;

            if (roundUp)
            {
                final = Math.Ceiling(final);
                tip = final - t;
            }
            else if (roundDown)
            {
                final = Math.Floor(final);
                tip = final - t;
            }

            tipOutput.Text = tip.ToString("C");
            totalOutput.Text = final.ToString("C");
        }
    }

    void OnNormalTip(object sender, EventArgs e) { tipPercentSlider.Value = 15; }
    void OnGenerousTip(object sender, EventArgs e) { tipPercentSlider.Value = 20; }
}

 

아래와 같이 변경할 것이다.

 

 

StatckLayOut 을 Spacing 이 40 인 Grid 로 변경한다. 

<Grid RowDefinitions="Auto, Auto, Auto, *, Auto, Auto, Auto"
      ColumnDefinitions="*, *"
      Padding="40">
    ...
</Grid>

다음 그림을 보고  grid 의 각 cell 에 배치하기 위해 row 와 column 을 지정하자.

row column 을 다 지정했다면 code 는 아래와 같을 것이다. 

Grid/MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.Grid.MainPage"
             Title="MainPage">
    <Grid RowDefinitions="Auto, Auto, Auto, *, Auto, Auto, Auto"
      ColumnDefinitions="*, *"
      Padding="40">

        <Label Text="Bill" 
               Grid.Row="0" 
               Grid.Column="0" />
        <Entry x:Name="billInput"
               Placeholder="Enter Amount" 
               Keyboard="Numeric" 
               Grid.Row="0" 
               Grid.Column="1" />

        <Label Text="Tip" Grid.Row="1" Grid.Column="0"/>
        <Label x:Name="tipOutput" Text="0.00" Grid.Row="1" Grid.Column="1"/>

        <Label Text="Total" Grid.Row="2" Grid.Column="0"/>
        <Label x:Name="totalOutput" Text="0.00" Grid.Row="2" Grid.Column="1" />

        <Label Text="Tip Percentage" Grid.Row="3" Grid.Column="0"/>
        <Label x:Name="tipPercent" Text="15%" Grid.Row="3" Grid.Column="1"/>
        <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" 
                Grid.Row="4" Grid.Column="0"/>

        <Button Text="15%" Clicked="OnNormalTip" Grid.Row="5" Grid.Column="0"/>
        <Button Text="20%" Clicked="OnGenerousTip" Grid.Row="5" Grid.Column="1"/>

        <Button x:Name="roundDown" Text="Round Down" Grid.Row="6" Grid.Column="0"/>
        <Button x:Name="roundUp"   Text="Round Up" Grid.Row="6" Grid.Column="1"/>

    </Grid>
</ContentPage>

실행

 

Bill 과 관련된 상단 Label 이 상단(Top)으로 정렬 되어 있다. 

VerticalOptions 를 이용하여 Center 로 정렬을 바꾸자

<Label Text="Bill" Grid.Row="0" Grid.Column="0" VerticalOptions="Center"/>

 

Slider 가 하나의 Cell 에만 표현된다. 이문제를 해결하기 위해 ColumnSpan 을 사용하자

<Slider ... Grid.ColumnSpan="2" ... />

 

Tip Percentage 를 찾아서 위치를 왼쪽 하단으로 가도록 해보자

<Label Text="Tip Percentage" VerticalOptions="End" HorizontalOptions="Start" ... />

15% 를 찾아서 위치를 오른쪽 하단으로 가도록 하자.

<Label x:Name="tipPercent" VerticalOptions="End" HorizontalOptions="End" ... />

각 버튼에 Margin 을 5 주자

 

완성된 코드는 아래와 같다. 

Grid/MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Xaml.Grid.MainPage"
             Title="MainPage">
    <Grid RowDefinitions="Auto, Auto, Auto, *, Auto, Auto, Auto"
      ColumnDefinitions="*, *"
      Padding="40">

        <Label Text="Bill" Grid.Row="0" Grid.Column="0" VerticalOptions="Center"/>
        <Entry x:Name="billInput" Placeholder="Enter Amount" Keyboard="Numeric" 
               Grid.Row="0" Grid.Column="1" />

        <Label Text="Tip" Grid.Row="1" Grid.Column="0"/>
        <Label x:Name="tipOutput" Text="0.00" Grid.Row="1" Grid.Column="1"/>

        <Label Text="Total" Grid.Row="2" Grid.Column="0"/>
        <Label x:Name="totalOutput" Text="0.00" Grid.Row="2" Grid.Column="1" />

        <Label Text="Tip Percentage" Grid.Row="3" Grid.Column="0"
               VerticalOptions="End" HorizontalOptions="Start"/>
        <Label x:Name="tipPercent" Text="15%" Grid.Row="3" Grid.Column="1"
               VerticalOptions="End" HorizontalOptions="End"/>
        <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" 
                Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"/>

        <Button Text="15%" Clicked="OnNormalTip" Grid.Row="5" Grid.Column="0" Margin="5" />
        <Button Text="20%" Clicked="OnGenerousTip" Grid.Row="5" Grid.Column="1" Margin="5" />

        <Button x:Name="roundDown" Text="Round Down" Grid.Row="6" Grid.Column="0" Margin="5" />
        <Button x:Name="roundUp"   Text="Round Up" Grid.Row="6" Grid.Column="1" Margin="5" />

    </Grid>
</ContentPage>

실행

 

 

 

 

관련영상

https://youtu.be/U8UfUQR5ng8

 

 

 

반응형