카테고리 없음

.NET MAUI - CommunityToolkit.Maui.Markup

yogingang 2022. 8. 29. 00:00
반응형

C# 마크업은 코드에서 .NET MAUI 사용자 인터페이스를 단순화하도록 설계된 도우미 메서드 및 클래스 집합이다. C# Markup에서 제공하는 API는 CommunityToolkit.Maui.Markup 을 통해 사용할 수 있다. 

 

XAML과 마찬가지로 C# 마크업을 사용하면 UI와 비즈니스 로직을 명확하게 구분할 수 있다.
C# 마크업은 .NET MAUI에서 지원하는 모든 플랫폼에서 사용할 수 있다.

 

사용하기 위해서는 nuget package 를 통해 다음을 설치 한다. 

 

설치

 

다음과 같은 MainPage.xaml 이 있다고 가정하자

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.Markup.MainPage"
             xmlns:local="clr-namespace:MauiApp1.Markup"
             x:DataType="local:MainViewModel"
             Title="MainPage">
    <ContentPage.BindingContext>
        <local:MainViewModel />
    </ContentPage.BindingContext>
    <VerticalStackLayout Padding="10" Spacing="20">
        <Label 
            Text="{Binding Name}" 
            VerticalOptions="Center"
            HorizontalOptions="Center"
            FontSize="24"/>

        <Button Command="{Binding ChangeNameCommand}" Text="Change Name" />
    </VerticalStackLayout>
</ContentPage>

MainPage.xaml.cs

namespace MauiApp1.Markup;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
	}
}

MainViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace MauiApp1.Markup;
public partial class MainViewModel : ObservableObject
{
    public MainViewModel()
    {
        Name = "My Name is Yogingang";
    }
    [ObservableProperty]
    private string name;
    [RelayCommand]
    private void ChangeName() => Name = $"{DateTime.UtcNow} : Change New Name";
}

 

위에 코드는 button 을 클릭시 현재 시간을 utc 기준으로 표시하고 Change New Name 을 찍는 간단한 app  이다. 

지금 까지 공부했던 CommunityToolkit.MVVM 을 이용하였다. 

 

위 코드중 XAML 로 이루어진 design 부분을 C# Markup 을 이용해 다시 구현해 보겠다. 

 

MauiProgram.cs

using CommunityToolkit.Maui.Markup;
using MauiMarkup.InjectableServices;

namespace MauiMarkup;
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder.UseMauiApp<App>()
               .UseMauiCommunityToolkitMarkup()
               .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

        builder.Services.Scan(scan => scan
                           .FromAssemblyOf<ITransientService>()
                           .AddClasses(classes => classes.AssignableTo<ITransientService>())
                           .AsSelfWithInterfaces()
                           .WithTransientLifetime()
                           .AddClasses(classes => classes.AssignableTo<IScopedService>())
                           .AsSelfWithInterfaces()
                           .WithScopedLifetime()
                           .AddClasses(classes => classes.AssignableTo<ISingletonService>())
                           .AsSelfWithInterfaces()
                           .WithSingletonLifetime()
                           );

        return builder.Build();
    }
}

AppShell.cs

using MauiMarkup.InjectableServices;

namespace MauiMarkup;

public partial class AppShell : Shell, ITransientService
{
	public AppShell(MainPage mainPage)
	{
		Items.Add(mainPage);
	}
}

App.cs

using MauiMarkup.InjectableServices;

namespace MauiMarkup;
public class App : Application, ISingletonService
{
    public App(AppShell shell)
    {
        MainPage = shell;
    }
}

InjectableServices/Injectable.cs

namespace MauiMarkup.InjectableServices;
public interface IInjectableService { }
public interface ITransientService : IInjectableService { }
public interface IScopedService : IInjectableService { }
public interface ISingletonService : IInjectableService { }

MainPage.cs

using CommunityToolkit.Maui.Markup;
using MauiMarkup.InjectableServices;

namespace MauiMarkup;
public class MainPage : ContentPage, ITransientService
{
    public MainPage(MainViewModel mainViewModel)
    {
        BindingContext = mainViewModel;
        Build();
    }

    void Build()
    {
        Content = new VerticalStackLayout
        {
            Padding = 10,
            Spacing = 20,
            Children =
            {
                new Label()
                .Bind("Name")
                .CenterVertical()
                .CenterHorizontal()
                .Font(size:24),

                new Button()
                .Bind("ChangeNameCommand")
                .Text("Change Name"),

            }
        };
    }
}

 

XAML 과 관련된 page 들은 전부 삭제 되었고

Behind code 로 되어 있는 file 들의 이름의 {Name}.XAML.cs 에서 {Name}.cs 로 변경되었다.

Scrutor 과 Dependency Injection 을 활용하여 ViewModel 을 주입받고 있다. 

가장중요한 MainPage.cs 를 보면 아주 깔끔한(????) c# code 로 이루어 진것을 볼수 있다. 

(사실 개인적으로 이런형태의 개발을 좋아하지는 않는다......

Designer 가 XAML 보다 이것을 잘 사용할 거라고 생각돼지 않는다.)

 

만약 회사에 디자이너가 XAML 을 알고 있거나 또는 전문적인 Design 팀 (GUI 개발) 이 있다면

c# markup 보다는 XAML 과  mvvm 모델을 이용하자

 

 

관련영상

https://youtu.be/BP9jpfAOa4M

 

반응형