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 모델을 이용하자
관련영상