.NET MAUI - XAML 리소스 정의 및 사용

2022. 7. 14. 00:00MAUI

반응형

리소스는 프로그래밍 언어의 Constant 와 같다. 한곳에서 정의 하고 필요한 곳에서 참조 한다.

값을 변경해야 하는 경우 정의만 업데이트 하면 모두에 적용된다.

 

리소스는 UI 전체에서 공유할 수 있는 모든 개체이다. 일반적으로 글꼴, 색상 및 크기를 저장한다. 

그러나 Style 및 OnPlatform 인스턴스와 같은 복잡한 개체를 리소스로 저장할 수도 있다.

XAML 또는 코드에서 리소스를 정의한다. 그런 다음 XAML 또는 코드에 적용한다.

일반적으로 XAML에서 완전히 작업하지만  코드가 유용한 몇 가지 경우도 있다.

페이지의 컨트롤에서 동일한 TextColor 값을 사용하려고 한다고 가정한다.

하드 코딩된 값을 사용한 경우 XAML은 다음과 같다. 

 

<Label TextColor="Blue" FontSize="14">
<Button TextColor="Blue" FontSize="14">

Resource 로 정의 하면 다음과 같이 정의 할 수 있다. 

<Color x:Key="PageControlTextColor">Blue</Color>

x:Key 를 이용하여 리소스를 조회 하고 사용 할 수 있다. 

 

리소스를 사용하려면 먼저 리소스 사전(ResourceDictionary)에 저장해야 한다.

 

ResourceDictionary는 UI 리소스와 함께 사용하도록 사용자 지정된 .NET MAUI 라이브러리 클래스이다. 

key / value 형태로 저장한다. key의 유형은 문자열로 제한되지만 value는 모든 개체가 될 수 있다.

XAML 페이지에는 ResourceDictionary 개체를 보유할 수 있는 Resources라는 속성이 있다.

다음 코드는 ResourceDictionary 개체를 만들고 이를 ContentPage의 Resources 속성에 할당하는 방법을 보여준다.

<ContentPage.Resources>
    <ResourceDictionary>
        ...
    </ResourceDictionary>
</ContentPage.Resources>

위 구문은 아래와 같이 단순화 할 수 있다. 

<ContentPage.Resources>
    ...
</ContentPage.Resources>

 

리소스 생성

<ContentPage.Resources>
    <Color x:Key="PageControlTextColor">Blue</Color>
</ContentPage.Resources>

StaticResource 를 사용하여 리소스 적용

<ContentPage.Resources>
    <Color x:Key="PageControlTextColor">Blue</Color>
</ContentPage.Resources>

...

<Label TextColor="{StaticResource PageControlTextColor}" ... />

** StaticResource 는 해당 Key 를 발견하지 못하면 runtime exception 이 발생한다. **

 

플랫폼별 리소스 생성

<ContentPage.Resources>
    <OnPlatform x:Key="textColor" x:TypeArguments="Color">
        <On Platform="iOS" Value="Silver" />
        <On Platform="Android" Value="Green" />
        <On Platform="WinUI" Value="Yellow" />
        <On Platform="MacCatalyst" Value="Pink" />
    </OnPlatform> 
</ContentPage.Resources>
...

<Label TextColor="{StaticResource textColor}" ... />

 

예제

ResourceDictionary/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.ResourceDictionary.MainPage"
             Title="MainPage">
    <Grid x:Name ="LayoutRoot" BackgroundColor="Silver" Padding="10"
          ColumnDefinitions="*, 3*"
          RowDefinitions="Auto, Auto, Auto, Auto, *">


        <!-- Left column = static labels -->
        <Label x:Name="billLabel"  Text="Bill"  TextColor="Navy" FontSize="22" FontAttributes="Bold" Grid.Row="0" Grid.Column="0" />
        <Label x:Name="tipLabel"   Text="Tip"   TextColor="Navy" FontSize="22" FontAttributes="Bold" Grid.Row="1" Grid.Column="0" />
        <Label x:Name="totalLabel" Text="Total" TextColor="Navy" FontSize="22" FontAttributes="Bold" Grid.Row="2" Grid.Column="0" />

        <!-- Right column = user input and calculated-value output -->
        <Entry x:Name="billInput"   Placeholder="Enter Amount" Keyboard="Numeric" TextColor="Gray" Grid.Row="0" Grid.Column="1" />
        <Label x:Name="tipOutput"   Text="0.00" TextColor="Navy" FontSize="22"   Grid.Row="1" Grid.Column="1" />
        <Label x:Name="totalOutput" Text="0.00" TextColor="Navy" FontSize="22"   Grid.Row="2" Grid.Column="1" />

        <!-- Navigate to advanced-view page -->
        <Button Text="Use Custom Calculator" Clicked="GotoCustom" TextColor="White" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" />

        <!-- Swap the foreground/background colors of this page -->
        <HorizontalStackLayout HorizontalOptions="Center" VerticalOptions="End" Spacing="100" Grid.Row="4" Grid.ColumnSpan="2">
            <Button Clicked="OnLight" Text="Light" TextColor="White" Grid.Column="0" />
            <Button Clicked="OnDark"  Text="Dark"  TextColor="White" Grid.Column="1" />
        </HorizontalStackLayout>

    </Grid>
</ContentPage>

ResourceDictionary/MainPage.xaml.cs

namespace MauiApp1.Xaml.ResourceDictionary;

public partial class MainPage : ContentPage
{
    private Color colorNavy = Colors.Navy;
    private Color colorSilver = Colors.Silver;

    public MainPage()
	{
		InitializeComponent();
	}
    void CalculateTip()
    {
        double bill;

        if (Double.TryParse(billInput.Text, out bill) && bill > 0)
        {
            double tip = Math.Round(bill * 0.15, 2);
            double final = bill + tip;

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

    void OnLight(object sender, EventArgs e)
{
        LayoutRoot.BackgroundColor = colorSilver;

        tipLabel.TextColor = colorNavy;
        billLabel.TextColor = colorNavy;
        totalLabel.TextColor = colorNavy;
        tipOutput.TextColor = colorNavy;
        totalOutput.TextColor = colorNavy;
    }

    void OnDark(object sender, EventArgs e)
    {
        LayoutRoot.BackgroundColor = colorNavy;

        tipLabel.TextColor = colorSilver;
        billLabel.TextColor = colorSilver;
        totalLabel.TextColor = colorSilver;
        tipOutput.TextColor = colorSilver;
        totalOutput.TextColor = colorSilver;
    }

    async void GotoCustom(object sender, EventArgs e)
    {
        await Shell.Current.GoToAsync(nameof(CustomTipPage));
    }
}

ResourceDictionary/CustomTipPage.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.ResourceDictionary.CustomTipPage"
             Title="CustomTipPage">
    <Grid x:Name ="LayoutRoot" Padding="10"
          ColumnDefinitions="*,2*"
          RowDefinitions="Auto, Auto, Auto, *">

        <Label x:Name="billLabel"  Text="Bill"  FontSize="22" FontAttributes="Bold" Grid.Row="0" Grid.Column="0" />
        <Label x:Name="tipLabel"   Text="Tip"   FontSize="22" FontAttributes="Bold" Grid.Row="1" Grid.Column="0" />
        <Label x:Name="totalLabel" Text="Total" FontSize="22" FontAttributes="Bold" Grid.Row="2" Grid.Column="0" />

        <Entry x:Name="billInput"   Placeholder="Enter Amount" Keyboard="Numeric" Grid.Row="0" Grid.Column="1" />
        <Label x:Name="tipOutput"   Text="0.00" FontSize="22" Grid.Row="1" Grid.Column="1" />
        <Label x:Name="totalOutput" Text="0.00" FontSize="22" Grid.Row="2" Grid.Column="1" />

        <Grid Grid.Row="3" Padding="10" ColumnSpacing="10" RowSpacing="10"
              Grid.Column="0" 
              Grid.ColumnSpan="2" VerticalOptions="End"
              ColumnDefinitions="*,*"
              RowDefinitions="Auto,Auto,Auto,Auto">


            <Label Text="Tip Percentage" FontSize="Medium" FontAttributes="Bold" Grid.Row="0" Grid.Column="0" />
            <Label x:Name="tipPercent" Text="15%" HorizontalOptions="End" VerticalTextAlignment="End" FontSize="Medium" Grid.Row="0" Grid.Column="1" />
            <Slider x:Name="tipPercentSlider" Minimum="0" Maximum="100" Value="15" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />

            <Button Text="15%" BorderColor="Pink" BorderWidth="2" Grid.Row="2" Grid.Column="0" Clicked="OnNormalTip" />
            <Button Text="20%" BorderColor="Pink" BorderWidth="2" Grid.Row="2" Grid.Column="1" Clicked="OnGenerousTip" />

            <Button x:Name="roundDown" Text="Round Down" BorderColor="Pink" BorderWidth="2" Grid.Row="3" Grid.Column="0" />
            <Button x:Name="roundUp"   Text="Round Up"   BorderColor="Pink" BorderWidth="2" Grid.Row="3" Grid.Column="1" />
        </Grid>
    </Grid>
</ContentPage>

 

ResourceDictionary/CustomTipPage.xaml.cs

namespace MauiApp1.Xaml.ResourceDictionary;
public partial class CustomTipPage : ContentPage
{
    public CustomTipPage()
    {
        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; }
}

 

MainPage.xaml 파일을 확인한다. 

LayoutRoot 그리드의 배경색을 설정하는 XAML 태그를 찾는다. 하드코딩되어 있다. 

TextColor 를 Navy 를 쓰고 FontSize 가 22 인 XAML 태그를 찾는다. 반복해서 사용중이다.

다섯곳에서 반복해서 사용하고 있다. 이부분을 resource 로 정의 해 보자

 

Resource 정의

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             ...>

    <ContentPage.Resources>
        <ResourceDictionary>
            <Color x:Key="bgColor">#C0C0C0</Color>
            <Color x:Key="fgColor">#0000AD</Color>
            <x:Double x:Key="fontSize">22</x:Double>
        </ResourceDictionary>
    </ContentPage.Resources>

    <Grid x:Name ="LayoutRoot" ...>
        ...

 

Static resource 를 이용하여 적용

...
<Grid x:Name ="LayoutRoot" BackgroundColor="{StaticResource bgColor}" Padding="10">
...
<!-- Left column = static labels -->
<Label x:Name="billLabel"  Text="Bill"  TextColor="{StaticResource fgColor}" FontSize="{StaticResource fontSize}" ... />
<Label x:Name="tipLabel"   Text="Tip"   TextColor="{StaticResource fgColor}" FontSize="{StaticResource fontSize}" ... />
<Label x:Name="totalLabel" Text="Total" TextColor="{StaticResource fgColor}" FontSize="{StaticResource fontSize}" ... />
...
<Label x:Name="tipOutput"   Text="0.00" 
       TextColor="{StaticResource fgColor}" 
       FontSize="{StaticResource fontSize}"  
       Grid.Row="1" Grid.Column="1" />
<Label x:Name="totalOutput" Text="0.00" 
       TextColor="{StaticResource fgColor}" 
       FontSize="{StaticResource fontSize}"   
       Grid.Row="2" Grid.Column="1" />

 

마지막으로 AppShell.xaml.cs 의 생성자에 다음 코드를 추가하자.

CustomTipPage 로 이동하기 위해 Routing 경로에 추가하는 작업이다. 

Routing.RegisterRoute(nameof(CustomTipPage), typeof(CustomTipPage));

 

 

관련영상

https://youtu.be/_mG6DseF5Xs

 

 

반응형