작은 팁: Avalonia 디자이너와 AppHost Avalonia를 모두 존중하는 Program.cs 예시

개인적으로 가능한 모든 애플리케이션의 진입점을 AppHost 기반으로 통합할 수 있다면 좋겠다는 생각이 있는데, 아쉽게도 Avalonia는 이 부분에 대한 대응이 다소 느린 편입니다.

Avalonia에서 AppHost를 사용할 수 있도록 돕는 nuget 패키지도 Avalonia 측이 아닌 서드 파티를 사용하는 것이 최선인데, 문제는 이 패키지를 사용하여 Main 메서드 구성을 바꾸면 디자이너가 필요로 하는 구성을 유지할 수 없다는 문제가 있습니다.

다행히도, 디자이너가 프리뷰를 표현하기 위해서 찾는 요소가 그다지 복잡하지 않고, BuildAvaloniaApp 메서드의 존재 여부만 확인해서 호출하는 것이 전부이다보니 아래와 같이 약간의 nudge를 시도하면 AppHost와 디자이너가 같은 설정을 공유하면서도, axaml 디자이너가 정상적으로 axaml 프리뷰를 표시할 수 있게 존중할 수 있었습니다.

using Avalonia;
using Lemon.Hosting.AvaloniauiDesktop;
using Microsoft.Extensions.Hosting;
using System;
using System.Runtime.Versioning;

namespace AvaloniaTestDrive;

// required nuget Package: <PackageReference Include="Lemon.Hosting.AvaloniauiDesktop" Version="1.0.0" />

// For use with Avalonia Designer, you should not convert to a Top-level statement.
internal static class Program
{
    [STAThread]
    [SupportedOSPlatform("windows")]
    public static void Main(string[] args)
    {
        var builder = Host.CreateApplicationBuilder(args);
        builder.Services.AddAvaloniauiDesktopApplication<App>(BuildAvaloniaApp);

        var app = builder.Build();
        app.RunAvaloniauiApplication(args);
    }

    // This method is used by both AppHost Avalonia runtime and the Avalonia Designer.
    private static AppBuilder BuildAvaloniaApp(AppBuilder? app)
    {
        if (app == null)
            app = AppBuilder.Configure<App>();

        return app
            .UsePlatformDetect()
            .WithInterFont()
            .LogToTrace();
    }

    // This method is required for use with the Avalonia designer.
    // The Avalonia designer will look for this method regardless of whether or not it is private.
    private static AppBuilder BuildAvaloniaApp()
        => BuildAvaloniaApp(null);
}

이 문제로 고민하고 계신 분들께 도움이 될 수 있을까하여 팁을 공유해봅니다.

6개의 좋아요

저도 아발로니아에서 호스트를 사용해보기 위해서 테스트해본적이 있습니다.

제가 시도하던때에는 닷넷 10 기능 program.cs 만으로 실행하는 것이 나오진 않았던 때이고, 디자인 템플릿등을 이용하려면 App.axaml.cs 가 필요하다 느껴서 저는 App.axaml.cs에서 호스트를 생성하는 방식으로 진행했습니다.

마찬가지로 프리뷰가 정상적으로 로드되지 않는 문제를 겪었고, 명확한 내용은 확인하지 못하였지만 public override void OnFrameworkInitializationCompleted() 안에서 처리가 되면 정상적으로 프리뷰로드가 되는것을 확인 했습니다.

해당 깃 퍼블릭으로 변경하고 공유합니다. 혹시 제코드에 문제될 사양이 있다면 부담없이 댓글 달아주세요

6개의 좋아요