다음을 통해 공유


네이티브 포함

샘플을 찾아봅니다. 샘플 찾아보기

일반적으로 .NET 다중 플랫폼 앱 UI(.NET MAUI) 앱에는 레이아웃(예: Grid및 보기 Button가 포함된 레이아웃)이 포함된 페이지가 포함됩니다. 페이지, 레이아웃 및 뷰는 모두 .에서 Element파생됩니다. 네이티브 포함을 사용하면 Android용 .NET, iOS용 .NET, Mac Catalyst용 .NET 및 WinUI 네이티브 앱에서 Element 파생되는 모든 .NET MAUI 컨트롤을 사용할 수 있습니다.

네이티브 앱에서 .NET MAUI 컨트롤을 사용하는 프로세스는 다음과 같습니다.

  1. 네이티브 임베디드 앱을 부트스트랩하는 확장 메서드를 만듭니다. 자세한 내용은 확장 메서드 만들기를 참조 하세요.
  2. .NET MAUI UI 및 모든 종속성이 포함된 .NET MAUI 단일 프로젝트를 만듭니다. 자세한 내용은 .NET MAUI 단일 프로젝트 만들기를 참조 하세요.
  3. 네이티브 앱을 만들고 .NET MAUI 지원을 사용하도록 설정합니다. 자세한 내용은 .NET MAUI 지원 사용을 참조 하세요.
  4. 네이티브 앱 프로젝트에서 .NET MAUI를 초기화합니다. 자세한 내용은 .NET MAUI 초기화를 참조 하세요.
  5. .NET MAUI UI를 만들고 확장 메서드를 사용하여 적절한 네이티브 형식으로 ToPlatformEmbedding 변환합니다. 자세한 내용은 .NET MAUI 컨트롤을 사용합니다.
  1. .NET MAUI UI 및 모든 종속성이 포함된 .NET MAUI 단일 프로젝트를 만듭니다. 자세한 내용은 .NET MAUI 단일 프로젝트 만들기를 참조 하세요.
  2. 네이티브 앱을 만들고 .NET MAUI 지원을 사용하도록 설정합니다. 자세한 내용은 .NET MAUI 지원 사용을 참조 하세요.
  3. 네이티브 앱 프로젝트에서 .NET MAUI를 초기화합니다. 자세한 내용은 .NET MAUI 초기화를 참조 하세요.
  4. .NET MAUI UI를 만들고 확장 메서드를 사용하여 적절한 네이티브 형식으로 ToPlatformEmbedding 변환합니다. 자세한 내용은 .NET MAUI 컨트롤을 사용합니다.

참고 항목

네이티브 포함을 사용하는 경우 .NET MAUI의 데이터 바인딩 엔진은 여전히 작동합니다. 그러나 네이티브 탐색 API를 사용하여 페이지 탐색을 수행해야 합니다.

확장 메서드 만들기

.NET MAUI 컨트롤을 사용하는 네이티브 앱을 만들기 전에 먼저 .NET MAUI 클래스 라이브러리 프로젝트를 만들고 Platforms 폴더와 클래스를 Class1 삭제해야 합니다. 그런 다음, 다음 코드를 포함하는 클래스를 명명 EmbeddedExtensions 된 클래스에 추가합니다.

using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.Platform;

#if ANDROID
using PlatformView = Android.Views.View;
using PlatformWindow = Android.App.Activity;
using PlatformApplication = Android.App.Application;
#elif IOS || MACCATALYST
using PlatformView = UIKit.UIView;
using PlatformWindow = UIKit.UIWindow;
using PlatformApplication = UIKit.IUIApplicationDelegate;
#elif WINDOWS
using PlatformView = Microsoft.UI.Xaml.FrameworkElement;
using PlatformWindow = Microsoft.UI.Xaml.Window;
using PlatformApplication = Microsoft.UI.Xaml.Application;
#endif

namespace Microsoft.Maui.Controls;

public static class EmbeddedExtensions
{
    public static MauiAppBuilder UseMauiEmbedding(this MauiAppBuilder builder, PlatformApplication? platformApplication = null)
    {
#if ANDROID
        platformApplication ??= (Android.App.Application)Android.App.Application.Context;
#elif IOS || MACCATALYST
        platformApplication ??= UIKit.UIApplication.SharedApplication.Delegate;
#elif WINDOWS
        platformApplication ??= Microsoft.UI.Xaml.Application.Current;
#endif

        builder.Services.AddSingleton(platformApplication);
        builder.Services.AddSingleton<EmbeddedPlatformApplication>();
        builder.Services.AddScoped<EmbeddedWindowProvider>();

        // Returning null is acceptable here as the platform window is optional - but we don't know until we resolve it
        builder.Services.AddScoped<PlatformWindow>(svc => svc.GetRequiredService<EmbeddedWindowProvider>().PlatformWindow!);
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IMauiInitializeService, EmbeddedInitializeService>());
        builder.ConfigureMauiHandlers(handlers =>
        {
            handlers.AddHandler(typeof(Window), typeof(EmbeddedWindowHandler));
        });

        return builder;
    }

    public static IMauiContext CreateEmbeddedWindowContext(this MauiApp mauiApp, PlatformWindow platformWindow, Window? window = null)
    {
        var windowScope = mauiApp.Services.CreateScope();

#if ANDROID
        var windowContext = new MauiContext(windowScope.ServiceProvider, platformWindow);
#else
        var windowContext = new MauiContext(windowScope.ServiceProvider);
#endif

        window ??= new Window();

        var wndProvider = windowContext.Services.GetRequiredService<EmbeddedWindowProvider>();
        wndProvider.SetWindow(platformWindow, window);
        window.ToHandler(windowContext);

        return windowContext;
    }

    public static PlatformView ToPlatformEmbedded(this IElement element, IMauiContext context)
    {
        var wndProvider = context.Services.GetService<EmbeddedWindowProvider>();
        if (wndProvider is not null && wndProvider.Window is Window wnd && element is VisualElement visual)
            wnd.AddLogicalChild(visual);

        return element.ToPlatform(context);
    }

    private class EmbeddedInitializeService : IMauiInitializeService
    {
        public void Initialize(IServiceProvider services) =>
            services.GetRequiredService<EmbeddedPlatformApplication>();
    }
}

이러한 확장 메서드는 네임스페이 Microsoft.Maui.Controls 스에 있으며 각 플랫폼에서 네이티브 임베디드 앱을 부트스트랩하는 데 사용됩니다. 확장 메서드 참조 EmbeddedPlatformApplicationEmbeddedWindowHandlerEmbeddedWindowProvider .NET MAUI 라이브러리 프로젝트에 추가해야 하는 형식입니다.

다음 코드는 클래스와 EmbeddedPlatformApplication 동일한 .NET MAUI 라이브러리 프로젝트에 추가되어야 하는 클래스를 EmbeddedExtensions 보여 있습니다.

#if ANDROID
using PlatformApplication = Android.App.Application;
#elif IOS || MACCATALYST
using PlatformApplication = UIKit.IUIApplicationDelegate;
#elif WINDOWS
using PlatformApplication = Microsoft.UI.Xaml.Application;
#endif

namespace Microsoft.Maui.Controls;

internal class EmbeddedPlatformApplication : IPlatformApplication
{
    private readonly MauiContext rootContext;
    private readonly IMauiContext applicationContext;

    public IServiceProvider Services { get; }
    public IApplication Application { get; }

    public EmbeddedPlatformApplication(IServiceProvider services)
    {
        IPlatformApplication.Current = this;

#if ANDROID
        var platformApp = services.GetRequiredService<PlatformApplication>();
        rootContext = new MauiContext(services, platformApp);
#else
        rootContext = new MauiContext(services);
#endif

        applicationContext = MakeApplicationScope(rootContext);
        Services = applicationContext.Services;
        Application = Services.GetRequiredService<IApplication>();
    }

    private static IMauiContext MakeApplicationScope(IMauiContext rootContext)
    {
        var scopedContext = new MauiContext(rootContext.Services);
        InitializeScopedServices(scopedContext);
        return scopedContext;
    }

    private static void InitializeScopedServices(IMauiContext scopedContext)
    {
        var scopedServices = scopedContext.Services.GetServices<IMauiInitializeScopedService>();

        foreach (var service in scopedServices)
            service.Initialize(scopedContext.Services);
    }
}

다음 코드는 클래스와 EmbeddedWindowHandler 동일한 .NET MAUI 라이브러리 프로젝트에 추가되어야 하는 클래스를 EmbeddedExtensions 보여 있습니다.

using Microsoft.Maui.Handlers;

#if ANDROID
using PlatformWindow = Android.App.Activity;
#elif IOS || MACCATALYST
using PlatformWindow = UIKit.UIWindow;
#elif WINDOWS
using PlatformWindow = Microsoft.UI.Xaml.Window;
#endif

namespace Microsoft.Maui.Controls;

internal class EmbeddedWindowHandler : ElementHandler<IWindow, PlatformWindow>, IWindowHandler
{
    public static IPropertyMapper<IWindow, IWindowHandler> Mapper =
        new PropertyMapper<IWindow, IWindowHandler>(ElementHandler.ElementMapper)
        {
        };

    public static CommandMapper<IWindow, IWindowHandler> CommandMapper =
        new CommandMapper<IWindow, IWindowHandler>(ElementHandler.ElementCommandMapper)
        {
        };

    public EmbeddedWindowHandler() : base(Mapper)
    {
    }

    protected override PlatformWindow CreatePlatformElement() =>
        MauiContext!.Services.GetRequiredService<PlatformWindow>() ??
        throw new InvalidOperationException("EmbeddedWindowHandler could not locate a platform window.");
}

다음 코드는 클래스와 EmbeddedWindowProvider 동일한 .NET MAUI 라이브러리 프로젝트에 추가되어야 하는 클래스를 EmbeddedExtensions 보여 있습니다.

#if ANDROID
using PlatformWindow = Android.App.Activity;
#elif IOS || MACCATALYST
using PlatformWindow = UIKit.UIWindow;
#elif WINDOWS
using PlatformWindow = Microsoft.UI.Xaml.Window;
#endif

namespace Microsoft.Maui.Controls;

public class EmbeddedWindowProvider
{
    WeakReference<PlatformWindow?>? platformWindow;
    WeakReference<Window?>? window;

    public PlatformWindow? PlatformWindow => Get(platformWindow);
    public Window? Window => Get(window);

    public void SetWindow(PlatformWindow? platformWindow, Window? window)
    {
        this.platformWindow = new WeakReference<PlatformWindow?>(platformWindow);
        this.window = new WeakReference<Window?>(window);
    }

    private static T? Get<T>(WeakReference<T?>? weak) where T : class =>
        weak is not null && weak.TryGetTarget(out var target) ? target : null;
}

.NET MAUI 단일 프로젝트 만들기

.NET MAUI 컨트롤을 사용하는 네이티브 앱을 만들기 전에 이전에 만든 .NET MAUI 클래스 라이브러리 프로젝트와 동일한 솔루션에 .NET MAUI 앱 프로젝트를 추가해야 합니다. .NET MAUI 앱 프로젝트는 네이티브 임베디드 앱에서 다시 사용하려는 UI를 저장합니다. 솔루션에 새 .NET MAUI 앱 프로젝트를 추가한 후 다음 단계를 수행합니다.

  1. 프로젝트에서 속성 폴더를 삭제합니다.

  2. 프로젝트에서 Platforms 폴더를 삭제합니다.

  3. 프로젝트에서 Resources/AppIcon 폴더를 삭제합니다.

  4. 프로젝트에서 Resources/raw 폴더를 삭제합니다.

  5. 프로젝트에서 Resources/Splash 폴더를 삭제합니다.

  6. AppShell 프로젝트에서 클래스를 삭제합니다.

  7. 클래스가 App 속성을 설정하거나 메서드를 MainPage 재정 CreateWindow 의하지 않는지 확인합니다.

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. MainPage 프로젝트에서 클래스를 삭제합니다.

  9. 빌드 속성이 $(TargetFramework) 설정 net8.0되고 $(OutputType) 빌드 속성이 제거되도록 프로젝트 파일을 수정합니다.

    <PropertyGroup>
      <TargetFramework>net8.0</TargetFramework>
    
      <RootNamespace>MyMauiApp</RootNamespace>
      <UseMaui>true</UseMaui>
      <SingleProject>true</SingleProject>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
    
      ...
    </PropertyGroup>
    

    Important

    빌드 속성이 $(TargetFramework) 아닌$(TargetFrameworks) 빌드 속성을 설정해야 합니다.

  10. 메서드 MauiProgramCreateMauiApp 반환되기 전에 호출되는 선택적 Action<MauiAppBuilder> 인수를 허용하게 클래스의 메서드를 수정합니다.

    public static MauiApp CreateMauiApp(Action<MauiAppBuilder>? additional = null)
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
    
        #if DEBUG
            builder.Logging.AddDebug();
        #endif
    
        additional?.Invoke(builder);
        return builder.Build();
    }
    

이 시점에서 종속성 및 리소스를 포함하여 필요한 .NET MAUI UI를 프로젝트에 추가하고 프로젝트가 올바르게 빌드되는지 확인해야 합니다.

.NET MAUI 단일 프로젝트 만들기

.NET MAUI 컨트롤을 사용하는 네이티브 앱을 만들기 전에 이전에 만든 .NET MAUI 클래스 라이브러리 프로젝트와 동일한 솔루션에 .NET MAUI 앱 프로젝트를 추가해야 합니다. .NET MAUI 앱 프로젝트는 네이티브 임베디드 앱에서 다시 사용하려는 UI를 저장합니다. 솔루션에 새 .NET MAUI 앱 프로젝트를 추가한 후 다음 단계를 수행합니다.

  1. 프로젝트에서 속성 폴더를 삭제합니다.

  2. 프로젝트에서 Platforms 폴더를 삭제합니다.

  3. 프로젝트에서 Resources/AppIcon 폴더를 삭제합니다.

  4. 프로젝트에서 Resources/raw 폴더를 삭제합니다.

  5. 프로젝트에서 Resources/Splash 폴더를 삭제합니다.

  6. AppShell 프로젝트에서 클래스를 삭제합니다.

  7. 클래스가 App 속성을 설정하거나 메서드를 MainPage 재정 CreateWindow 의하지 않는지 확인합니다.

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. MainPage 프로젝트에서 클래스를 삭제합니다.

  9. 빌드 속성이 $(TargetFramework) 설정 net9.0되고 $(OutputType) 빌드 속성이 제거되도록 프로젝트 파일을 수정합니다.

    <PropertyGroup>
      <TargetFramework>net9.0</TargetFramework>
    
      <RootNamespace>MyMauiApp</RootNamespace>
      <UseMaui>true</UseMaui>
      <SingleProject>true</SingleProject>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
    
      ...
    </PropertyGroup>
    

    Important

    빌드 속성이 $(TargetFramework) 아닌$(TargetFrameworks) 빌드 속성을 설정해야 합니다.

  10. MauiProgram 클래스에서 제네릭 인수를 수락하도록 메서드를 TApp 수정 CreateMauiApp 하고 메서드가 반환되기 전에 호출되는 선택적 Action<MauiAppBuilder> 인수를 수락합니다. 또한 호출을 다음으로 UseMauiApp<App> 변경합니다 UseMauiEmbeddedApp<TApp>.

    public static class MauiProgram
    {
        // Create a MauiApp using the specified application.
        public static MauiApp CreateMauiApp<TApp>(Action<MauiAppBuilder>? additional = null) where TApp : App
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiEmbeddedApp<TApp>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });
    
            #if DEBUG
                builder.Logging.AddDebug();
            #endif
    
            additional?.Invoke(builder);
    
            return builder.Build();
        }
    }
    
  11. MauiProgram 클래스에서 선택적 Action<MauiAppBuilder> 인수를 CreateMauiApp 허용하는 오버로드를 추가합니다.

    public static class MauiProgram
    {
        ...
    
        // Create a MauiApp using the default application.
        public static MauiApp CreateMauiApp(Action<MauiAppBuilder>? additional = null) =>
            CreateMauiApp<App>(additional);
    }
    

그런 다음 종속성 및 리소스를 포함하여 필요한 .NET MAUI UI를 프로젝트에 추가하고 프로젝트가 올바르게 빌드되는지 확인해야 합니다.

.NET MAUI 지원 사용

Android용 .NET, iOS용 .NET, Mac Catalyst용 .NET 또는 WinUI 앱에서 Element 파생된 .NET MAUI 컨트롤을 사용하려면 네이티브 앱 프로젝트를 이전에 만든 .NET MAUI 클래스 라이브러리 프로젝트와 동일한 솔루션에 추가해야 합니다. 그런 다음 프로젝트 파일의 첫 번째 <PropertyGroup> 노드에서 속성을 true 설정하고 빌드하여 네이티브 앱의 프로젝트 파일에서 .NET MAUI 지원을 사용하도록 설정 $(UseMaui) $(MauiEnablePlatformUsings) 해야 합니다.

<PropertyGroup>
    ...
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>

    <UseMaui>true</UseMaui>
    <MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>  
</PropertyGroup>

Mac용 .NET Catalyst 앱의 경우 빌드 속성을 최소 14.0으로 설정 $(SupportedOSPlatformVersion) 해야 합니다.

<PropertyGroup>
    ...
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>

    <SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
    <UseMaui>true</UseMaui>
    <MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>  
</PropertyGroup>

Mac용 .NET Catalyst 앱의 경우 빌드 속성을 최소 15.0으로 설정 $(SupportedOSPlatformVersion) 해야 합니다.

<PropertyGroup>
    ...
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>

    <SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
    <UseMaui>true</UseMaui>
    <MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>  
</PropertyGroup>

WinUI 앱의 경우 빌드 속성을 false다음으로 설정 $(EnableDefaultXamlItems) 해야 합니다.

<PropertyGroup>
    ...
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>

    <UseMaui>true</UseMaui>
    <MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>    
    <EnableDefaultXamlItems>false</EnableDefaultXamlItems>
</PropertyGroup>

이렇게 하면 이미 정의되고 있는 메서드에 대한 InitializeComponent 빌드 오류가 수신되지 않습니다.

그런 다음, 프로젝트 파일 및 Microsoft.Maui.Controls.Compatiblity NuGet 패키지에 Microsoft.Maui.Controls 대한 빌드 항목을 추가 $(PackageReference) 합니다.

<ItemGroup>
    <PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
    <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
</ItemGroup>

그런 다음 NuGet 패키지의 프로젝트 파일에 Microsoft.Maui.Controls 빌드 항목을 추가 $(PackageReference) 합니다.

<ItemGroup>
    <PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
</ItemGroup>

.NET MAUI 초기화

네이티브 앱 프로젝트가 .NET MAUI 컨트롤을 생성하려면 먼저 .NET MAUI를 초기화해야 합니다. 초기화 시기는 주로 앱 흐름에서 가장 편리한 시기에 따라 달라집니다. 시작 시 또는 .NET MAUI 컨트롤이 생성되기 직전에 수행할 수 있습니다. 여기서 설명하는 방법은 앱의 초기 UI를 만들 때 .NET MAUI를 초기화하는 것입니다.

일반적으로 네이티브 앱 프로젝트에서 .NET MAUI를 초기화하는 패턴은 다음과 같습니다.

  • MauiApp 개체를 만듭니다.
  • 개체에서 MauiContext 개체를 만듭니다 MauiApp . 개체는 MauiContext .NET MAUI 뷰에서 네이티브 뷰를 가져오는 데 사용됩니다.

Android에서 클래스의 재정의 OnCreate MainActivity 는 일반적으로 앱 시작 관련 작업을 수행하는 위치입니다. 다음 코드 예제에서는 클래스에서 초기화되는 .NET MAUI를 MainActivity 보여줍니다.

namespace MyNativeEmbeddedApp.Droid;

[Activity(Label = "@string/app_name", MainLauncher = true, Theme = "@style/AppTheme")]
public class MainActivity : Activity
{
    public static readonly Lazy<MauiApp> MauiApp = new(() =>
    {
        var mauiApp = MauiProgram.CreateMauiApp(builder =>
        {
            builder.UseMauiEmbedding();
        });
        return mauiApp;
    });

    public static bool UseWindowContext = true;

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        // Ensure .NET MAUI app is built before creating .NET MAUI views
        var mauiApp = MainActivity.MauiApp.Value;

        // Create .NET MAUI context
        var context = UseWindowContext
            ? mauiApp.CreateEmbeddedWindowContext(this) // Create window context
            : new MauiContext(mauiApp.Services, this);  // Create app context

        ...              
    }
}

iOS 및 Mac Catalyst에서 재정의를 AppDelegate 위해 반환 true 하도록 클래스를 FinishedLaunching 수정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    public override UIWindow? Window { get; set; }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) => true;
}

WillConnect 그런 다음 클래스의 메서드를 SceneDelegate 수정하여 주 뷰 컨트롤러를 만들고 다음의 UINavigationController뷰로 설정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("SceneDelegate")]
public class SceneDelegate : UIResponder, IUIWindowSceneDelegate
{
    [Export("window")]
    public UIWindow? Window { get; set; }

    [Export("scene:willConnectToSession:options:")]
    public void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
    {
        if (scene is not UIWindowScene windowScene)
            return;

        Window = new UIWindow(windowScene);

        var mainVC = new MainViewController();
        var navigationController = new UINavigationController(mainVC);
        navigationController.NavigationBar.PrefersLargeTitles = true;

        Window.RootViewController = navigationController;
        Window.MakeKeyAndVisible();
    }

    ...
}

그런 다음 XML 편집기에서 Info.plist 파일을 열고 파일 끝에 다음 XML을 추가합니다.

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>Default Configuration</string>
        <key>UISceneDelegateClassName</key>
        <string>SceneDelegate</string>
      </dict>
    </array>
  </dict>
</dict>

그런 다음 기본 뷰 컨트롤러의 메서드에서 .NET MAUI를 ViewDidLoad 초기화할 수 있습니다.

using Microsoft.Maui.Platform;

namespace MyNativeEmbeddedApp.iOS;

public class MainViewController : UIViewController
{
    UIWindow GetWindow() =>
        View?.Window ??
        ParentViewController?.View?.Window ??
        MainViewController.MauiApp.Value.Services.GetRequiredService<IUIApplicationDelegate>().GetWindow() ??
        UIApplication.SharedApplication.Delegate.GetWindow();

    public static readonly Lazy<MauiApp> MauiApp = new(() =>
    {
        var mauiApp = MauiProgram.CreateMauiApp(builder =>
        {
            builder.UseMauiEmbedding();
        });
        return mauiApp;
    });

    public static bool UseWindowContext = true;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        // Ensure app is built before creating .NET MAUI views
        var mauiApp = MainViewController.MauiApp.Value;

        // Create .NET MAUI context
        var context = UseWindowContext
            ? mauiApp.CreateEmbeddedWindowContext(GetWindow()) // Create window context
            : new MauiContext(mauiApp.Services);               // Create app context

        ...
    }
}

Windows에서 MainWindow 클래스는 일반적으로 UI 관련 앱 시작 작업을 수행할 수 있는 위치입니다.

namespace MyNativeEmbeddedApp.WinUI;

public sealed partial class MainWindow : Microsoft.UI.Xaml.Window
{
    public static readonly Lazy<MauiApp> MauiApp = new(() =>
    {
        var mauiApp = MauiProgram.CreateMauiApp(builder =>
        {
            builder.UseMauiEmbedding();
        });
        return mauiApp;
    });

    public static bool UseWindowContext = true;

    public MainWindow()
    {
        this.InitializeComponent();

        // Ensure .NET MAUI app is built before creating .NET MAUI views
        var mauiApp = MainWindow.MauiApp.Value;

        // Create .NET MAUI context
        var context = UseWindowContext
            ? mauiApp.CreateEmbeddedWindowContext(this) // Create window context
            : new MauiContext(mauiApp.Services);        // Create app context

        ...
    }
}

이 예제에서는 MauiApp 지연 초기화를 사용하여 개체를 만듭니다. UseMauiEmbedding 확장 메서드는 개체에서 MauiAppBuilder 호출됩니다. 따라서 네이티브 앱 프로젝트에는 이 확장 메서드를 포함하는 만든 .NET MAUI 클래스 라이브러리 프로젝트에 대한 참조가 포함되어야 합니다. MauiContext 그런 다음 개체에서 컨텍스트의 MauiApp 범위를 결정하는 개체 bool 를 만듭니다. 개체는 MauiContext .NET MAUI 컨트롤을 네이티브 형식으로 변환할 때 사용됩니다.

포함은 앱 컨텍스트 또는 창 컨텍스트에서 수행할 수 있지만 최대 .NET MAUI 호환성을 위해 창 컨텍스트에서 수행해야 합니다.

앱 컨텍스트

네이티브 포함은 네이티브 앱이 창에 대한 지식이 없는 앱 컨텍스트에서 수행할 수 있습니다. 이 방법을 사용하면 네이티브 포함 초기화를 수행하려면 다음을 수행해야 합니다.

  • MauiApp 개체를 만듭니다.
  • 개체에서 MauiContext 개체를 만듭니다 MauiApp . 개체는 MauiContext .NET MAUI 뷰에서 네이티브 뷰를 가져오는 데 사용됩니다.

다음 예제에서는 이 방법을 보여 줍니다.

var mauiApp = MauiProgram.CreateMauiApp();
var context = new MauiContext(mauiApp.Services); // Activity also needs passing on Android

그런 다음 확장 메서드를 사용하여 .NET MAUI 뷰를 만들고 네이티브 뷰로 ToPlatformEmbedded 변환할 수 있습니다. 이때 개체를 인수로 사용해야 합니다 MauiContext .

이 방법은 네이티브 앱이 간단한 .NET MAUI UI를 포함해야 하지만 모든 .NET MAUI 기능에 액세스할 필요가 없는 시나리오에 적합합니다. 이 방법의 단점은 핫 다시 로드 및 일부 .NET MAUI 기능과 같은 도구가 작동하지 않는다는 것입니다.

MauiApp.NET MAUI 보기가 네이티브 뷰로 포함될 때마다 개체를 만드는 것은 권장되지 않습니다. 포함된 뷰가 속성에 Application.Current 액세스하는 경우 문제가 될 수 있습니다. 대신 개체를 MauiApp 공유 정적 인스턴스로 만들 수 있습니다.

public static class MyEmbeddedMauiApp
{
    static MauiApp? _shared;
    public static MauiApp Shared => _shared ??= MauiProgram.CreateMauiApp();
}

이 방법을 사용하면 앱 수명 주기 초기에 개체를 인스턴스화 MauiApp 하여 앱에 .NET MAUI 보기를 처음 포함할 때 약간의 지연을 방지할 수 있습니다.

Android에서 조각은 활동 내에서 UI의 일부를 나타냅니다. 다음 코드 예제에서는 조각에서 초기화되는 .NET MAUI를 보여줍니다.

using Android.Runtime;
using Android.Views;
using AndroidX.Navigation.Fragment;
using Microsoft.Maui.Controls.Embedding;
using Fragment = AndroidX.Fragment.App.Fragment;
using View = Android.Views.View;

namespace MyNativeEmbeddedApp.Droid;

[Register("com.companyname.nativeembeddingdemo." + nameof(FirstFragment))]
public class FirstFragment : Fragment
{
    public override View? OnCreateView(LayoutInflater inflater, ViewGroup? container, Bundle? savedInstanceState) =>
        inflater.Inflate(Resource.Layout.fragment_first, container, false);

    public override void OnViewCreated(View view, Bundle? savedInstanceState)
    {
        base.OnViewCreated(view, savedInstanceState);

        // Ensure .NET MAUI app is built before creating .NET MAUI views
        var mauiApp = MyEmbeddedMauiApp.Shared;

        // Create .NET MAUI context
        var context = new MauiContext(mauiApp.Services, Activity);

        ...
    }
}

iOS 및 Mac Catalyst에서 재정의를 AppDelegate 위해 반환 true 하도록 클래스를 FinishedLaunching 수정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    public override UIWindow? Window { get; set; }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) => true;
}

WillConnect 그런 다음 클래스의 메서드를 SceneDelegate 수정하여 주 뷰 컨트롤러를 만들고 다음의 UINavigationController뷰로 설정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("SceneDelegate")]
public class SceneDelegate : UIResponder, IUIWindowSceneDelegate
{
    [Export("window")]
    public UIWindow? Window { get; set; }

    [Export("scene:willConnectToSession:options:")]
    public void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
    {
        if (scene is not UIWindowScene windowScene)
            return;

        Window = new UIWindow(windowScene);

        var mainVC = new MainViewController();
        var navigationController = new UINavigationController(mainVC);
        navigationController.NavigationBar.PrefersLargeTitles = true;

        Window.RootViewController = navigationController;
        Window.MakeKeyAndVisible();
    }

    ...
}

그런 다음 XML 편집기에서 Info.plist 파일을 열고 파일 끝에 다음 XML을 추가합니다.

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>Default Configuration</string>
        <key>UISceneDelegateClassName</key>
        <string>SceneDelegate</string>
      </dict>
    </array>
  </dict>
</dict>

그런 다음 기본 뷰 컨트롤러의 메서드에서 .NET MAUI를 ViewDidLoad 초기화할 수 있습니다.

using Microsoft.Maui.Controls.Embedding;

namespace MyNativeEmbeddedApp.iOS;

public class MainViewController : UIViewController
{
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        // Ensure .NET MAUI app is built before creating .NET MAUI views
        var mauiApp = MyEmbeddedMauiApp.Shared;

        // Create .NET MAUI context
        var context = new MauiContext(mauiApp.Services);

        ...
    }
}

Windows에서 MainWindow 클래스는 일반적으로 UI 관련 앱 시작 작업을 수행할 수 있는 위치입니다.

using Microsoft.Maui.Controls.Embedding;
using Microsoft.UI.Xaml;

namespace MyNativeEmbeddedApp.WinUI;

public sealed partial class MainWindow : Microsoft.UI.Xaml.Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }

    private async void OnRootLayoutLoaded(object? sender, RoutedEventArgs e)
    {
        await Task.Yield();

        // Ensure .NET MAUI app is built before creating .NET MAUI views
        var mauiApp = MyEmbeddedMauiApp.Shared;

        // Create .NET MAUI context
        var context = new MauiContext(mauiApp.Services);

        ...
    }
}

이 예제에서는 개체가 MauiApp 공유 정적 인스턴스로 만들어집니다. 이 개체가 만들어 MauiProgram.CreateMauiApp 지면 개체에서 확장 메서드 MauiAppBuilderUseMauiEmbedding 호출하는 호출됩니다. 따라서 네이티브 앱 프로젝트에는 클래스와 .NET MAUI UI를 포함하는 만든 .NET MAUI 클래스 라이브러리 프로젝트에 대한 참조가 포함되어 MauiProgram 야 합니다. MauiContext 그런 다음 개체에서 개체로 MauiApp 범위가 지정된 개체를 MauiApp 만듭니다. 개체는 MauiContext .NET MAUI 컨트롤을 네이티브 형식으로 변환할 때 사용됩니다.

창 컨텍스트

네이티브 포함은 네이티브 앱에 창에 대한 지식이 있는 창 컨텍스트에서 수행할 수 있습니다. 일부 시나리오에서는 .NET MAUI 보기가 제대로 작동하려면 창에 대한 액세스 권한이 필요합니다. 예를 들어 적응형 트리거는 보기 창에 액세스해야 하며, 창이 없으면 작동하지 않습니다.

이 방법을 사용하면 네이티브 포함 초기화를 수행하려면 다음을 수행해야 합니다.

  • MauiApp 개체를 만듭니다.
  • 메서드를 사용하여 MauiContext 개체를 만듭니다 CreateEmbeddedWindowContext . 개체는 MauiContext .NET MAUI 뷰에서 네이티브 뷰를 가져오는 데 사용됩니다.

이 메서드는 CreateEmbeddedWindowContext 네이티브 창을 .NET MAUI 창과 관련된 창 컨텍스트를 만듭니다.

var mauiApp = MauiProgram.CreateMauiApp();
var context = mauiApp.CreateEmbeddedWindowContext(this);

그런 다음 확장 메서드를 사용하여 .NET MAUI 뷰를 만들고 네이티브 뷰로 ToPlatformEmbedded 변환할 수 있습니다. 이때 개체를 인수로 사용해야 합니다 MauiContext .

참고 항목

ToPlatformEmbedded 확장 메서드에는 포함된 창에 .NET MAUI 보기를 추가하는 오버로드가 있습니다.

이 방법의 장점은 각 네이티브 창에 대해 단일 .NET MAUI 창이 있고 창 관련 API가 올바르게 작동하며 핫 다시 로드와 같은 도구가 올바르게 작동한다는 것입니다.

MauiApp.NET MAUI 보기가 네이티브 뷰로 포함될 때마다 개체를 만드는 것은 권장되지 않습니다. 포함된 뷰가 속성에 Application.Current 액세스하는 경우 문제가 될 수 있습니다. 대신 개체를 MauiApp 공유 정적 인스턴스로 만들 수 있습니다.

public static class MyEmbeddedMauiApp
{
    static MauiApp? _shared;
    public static MauiApp Shared => _shared ??= MauiProgram.CreateMauiApp();
}

이 방법을 사용하면 앱 수명 주기 초기에 개체를 인스턴스화 MauiApp 하여 앱에 .NET MAUI 보기를 처음 포함할 때 약간의 지연을 방지할 수 있습니다.

Android에서 조각은 활동 내에서 UI의 일부를 나타냅니다. 다음 코드 예제에서는 조각에서 초기화되는 .NET MAUI를 보여줍니다.

using Android.Runtime;
using Android.Views;
using AndroidX.Navigation.Fragment;
using Microsoft.Maui.Controls.Embedding;
using Fragment = AndroidX.Fragment.App.Fragment;
using View = Android.Views.View;

namespace MyNativeEmbeddedApp.Droid;

[Register("com.companyname.nativeembeddingdemo." + nameof(FirstFragment))]
public class FirstFragment : Fragment
{
    Activity? _window;
    IMauiContext? _windowContext;

    public IMauiContext WindowContext =>
        _windowContext ??= MyEmbeddedMauiApp.Shared.CreateEmbeddedWindowContext(_window ?? throw new InvalidOperationException());

    public override View? OnCreateView(LayoutInflater inflater, ViewGroup? container, Bundle? savedInstanceState) =>
        inflater.Inflate(Resource.Layout.fragment_first, container, false);

    public override void OnViewCreated(View view, Bundle? savedInstanceState)
    {
        base.OnViewCreated(view, savedInstanceState);

        _window ??= Activity;

        // Create MAUI embedded window context
        var context = WindowContext;

        ...
    }
}

iOS 및 Mac Catalyst에서 재정의를 AppDelegate 위해 반환 true 하도록 클래스를 FinishedLaunching 수정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    public override UIWindow? Window { get; set; }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) => true;
}

WillConnect 그런 다음 클래스의 메서드를 SceneDelegate 수정하여 주 뷰 컨트롤러를 만들고 다음의 UINavigationController뷰로 설정해야 합니다.

namespace MyNativeEmbeddedApp.iOS;

[Register("SceneDelegate")]
public class SceneDelegate : UIResponder, IUIWindowSceneDelegate
{
    [Export("window")]
    public UIWindow? Window { get; set; }

    [Export("scene:willConnectToSession:options:")]
    public void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
    {
        if (scene is not UIWindowScene windowScene)
            return;

        Window = new UIWindow(windowScene);

        var mainVC = new MainViewController();
        var navigationController = new UINavigationController(mainVC);
        navigationController.NavigationBar.PrefersLargeTitles = true;

        Window.RootViewController = navigationController;
        Window.MakeKeyAndVisible();
    }

    ...
}

그런 다음 XML 편집기에서 Info.plist 파일을 열고 파일 끝에 다음 XML을 추가합니다.

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>Default Configuration</string>
        <key>UISceneDelegateClassName</key>
        <string>SceneDelegate</string>
      </dict>
    </array>
  </dict>
</dict>

그런 다음 기본 뷰 컨트롤러의 메서드에서 .NET MAUI를 ViewDidLoad 초기화할 수 있습니다.

using Microsoft.Maui.Controls.Embedding;

namespace MyNativeEmbeddedApp.iOS;

public class MainViewController : UIViewController
{
    UIKit.UIWindow? _window;
    IMauiContext? _windowContext;

    public IMauiContext WindowContext =>
        _windowContext ??= MyEmbeddedMauiApp.Shared.CreateEmbeddedWindowContext(_window ?? throw new InvalidOperationException());

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        _window ??= ParentViewController!.View!.Window;

        // Create MAUI embedded window context
        var context = WindowContext;

        ...
    }
}

Windows에서 MainWindow 클래스는 일반적으로 UI 관련 앱 시작 작업을 수행할 수 있는 위치입니다.

using Microsoft.Maui.Controls.Embedding;
using Microsoft.UI.Xaml;

namespace MyNativeEmbeddedApp.WinUI;

public sealed partial class MainWindow : Microsoft.UI.Xaml.Window
{
    Microsoft.UI.Xaml.Window? _window;
    IMauiContext? _windowContext;

    public IMauiContext WindowContext =>
        _windowContext ??= MyEmbeddedMauiApp.Shared.CreateEmbeddedWindowContext(_window ?? throw new InvalidOperationException());

    public MainWindow()
    {
        this.InitializeComponent();
        _window ??= this;
    }

    private async void OnRootLayoutLoaded(object? sender, RoutedEventArgs e)
    {
        await Task.Yield();

        // Create MAUI embedded window context
        var context = WindowContext;

        ...
    }
}

이 예제에서는 개체가 MauiApp 공유 정적 인스턴스로 만들어집니다. 이 개체가 만들어 MauiProgram.CreateMauiApp 지면 개체에서 확장 메서드 MauiAppBuilderUseMauiEmbedding 호출하는 호출됩니다. 따라서 네이티브 앱 프로젝트에는 클래스와 .NET MAUI UI를 포함하는 만든 .NET MAUI 클래스 라이브러리 프로젝트에 대한 참조가 포함되어 MauiProgram 야 합니다. MauiContext 그런 다음 창으로 범위가 CreateEmbeddedWindowContext 지정된 메서드를 사용하여 개체를 만듭니다. 개체는 MauiContext .NET MAUI 컨트롤을 네이티브 형식으로 변환할 때 사용됩니다.

.NET MAUI 컨트롤 사용

네이티브 앱에서 .NET MAUI가 초기화된 후 네이티브 앱의 레이아웃에 .NET MAUI UI를 추가할 수 있습니다. 이 작업은 UI의 인스턴스를 만들고 확장 메서드를 사용하여 적절한 네이티브 형식으로 ToPlatformEmbedded 변환하여 수행할 수 있습니다.

Android에서 확장 메서드는 ToPlatformEmbedded .NET MAUI 컨트롤을 Android View 개체로 변환합니다.

var mauiView = new MyMauiContent();
Android.Views.View nativeView = mauiView.ToPlatformEmbedded(context);

이 예제에서는 ContentView-derived 개체가 Android View 개체로 변환됩니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 이전에 만든 .NET MAUI 클래스 라이브러리에 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 프로젝트에 대한 참조가 포함되어야 합니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 네임스페이스에 Microsoft.Maui.Controls.Embedding 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 네임스페이 using 스에 대한 문이 포함되어야 합니다.

그러면 네이 View 티브 앱의 레이아웃에 개체를 추가할 수 있습니다.

rootLayout.AddView(nativeView, new LinearLayout.LayoutParams(MatchParent, WrapContent));

iOS 및 Mac Catalyst에서 ToPlatformEmbedded 확장 메서드는 .NET MAUI 컨트롤을 개체로 UIView 변환합니다.

var mauiView = new MyMauiContent();
UIView nativeView = mauiView.ToPlatformEmbedded(context);
nativeView.WidthAnchor.ConstraintEqualTo(View.Frame.Width).Active = true;
nativeView.HeightAnchor.ConstraintEqualTo(500).Active = true;

이 예제 ContentView에서는 파생 개체가 개체로 변환된 다음, 상호 작용을 UIView 허용하도록 너비 및 높이 제약 조건이 설정됩니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 이전에 만든 .NET MAUI 클래스 라이브러리에 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 프로젝트에 대한 참조가 포함되어야 합니다.

UIView 그런 다음 개체를 뷰 컨트롤러의 보기에 추가할 수 있습니다.

stackView.AddArrangedSubView(nativeView);
var mauiView = new MyMauiContent();
UIView nativeView = mauiView.ToPlatformEmbedded(context);

이 예제에서는 ContentView-derived 개체가 개체로 UIView 변환됩니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 네임스페이스에 Microsoft.Maui.Controls.Embedding 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 네임스페이 using 스에 대한 문이 포함되어야 합니다.

UIView 그런 다음 개체를 뷰 컨트롤러의 보기에 추가할 수 있습니다.

stackView.AddArrangedSubView(new ContainerView(nativeView));

ContainerView 는 .NET MAUI 뷰의 크기를 올바르게 조정하는 사용자 지정 형식입니다. .NET MAUI 보기로 리디렉션하여 IntrinsicContentSize 이 작업을 수행합니다 SizeThatFits.

class ContainerView : UIView
{
    public ContainerView(UIView view)
    {
        AddSubview(view);
    }

    public override CGSize IntrinsicContentSize =>
        SizeThatFits(new CGSize(nfloat.MaxValue, nfloat.MaxValue));

    public override CGSize SizeThatFits(CGSize size) =>
        Subviews?.FirstOrDefault()?.SizeThatFits(size) ?? CGSize.Empty;

    public override void LayoutSubviews()
    {
        if (Subviews?.FirstOrDefault() is { } view)
            view.Frame = Bounds;
    }

    public override void SetNeedsLayout()
    {
        base.SetNeedsLayout();
          InvalidateIntrinsicContentSize();
    }
}

또한 .NET MAUI의 ToUIViewController 확장 메서드를 사용하여 .NET MAUI 페이지를 다음으로 변환할 UIViewController수 있습니다.

MyMauiPage myMauiPage = new MyMauiPage();
UIViewController myPageController = myMauiPage.ToUIViewController(context);

이 예제에서는 ContentPage-derived 개체가 .로 변환 UIViewController됩니다.

Windows에서 확장 메서드는 ToPlatformEmbedded .NET MAUI 컨트롤을 개체로 FrameworkElement 변환합니다.

var mauiView = new MyMauiContent();
FrameworkElement nativeView = myMauiPage.ToPlatformEmbedded(context);

이 예제에서는 ContentView-derived 개체가 개체로 FrameworkElement 변환됩니다. 그런 다음 개체를 FrameworkElement WinUI 페이지의 콘텐츠로 설정할 수 있습니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 이전에 만든 .NET MAUI 클래스 라이브러리에 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 프로젝트에 대한 참조가 포함되어야 합니다.

참고 항목

ToPlatformEmbedded 확장 메서드는 네임스페이스에 Microsoft.Maui.Controls.Embedding 있습니다. 따라서 네이티브 앱 프로젝트에는 해당 네임스페이 using 스에 대한 문이 포함되어야 합니다.

그러면 네이 FrameworkElement 티브 앱의 레이아웃에 개체를 추가할 수 있습니다.

stackPanel.Children.Add(nativeView);

Important

오류가 발생하지 않도록 하려면 디버그 구성에서 네이티브 포함된 앱을 실행하기 전에 XAML 핫 다시 로드를 사용하지 않도록 설정해야 합니다.

XAML 핫 다시 로드 지원

XAML 핫 다시 로드는 네이티브 임베디드 앱에서 지원되지 않습니다. 그러나 .NET MAUI UI를 사용하는 .NET MAUI 앱을 만들어 XAML 핫 다시 로드를 사용하여 .NET MAUI UI에서 빠르게 반복할 수 있습니다.

XAML 핫 다시 로드를 사용하여 .NET MAUI UI를 보려면 다음을 수행합니다.

  1. .NET MAUI UI가 포함된 프로젝트에서 클래스를 MauiProgram 업데이트하여 오버로드를 추가하고 CreateMauiApp 제네릭 인수를 허용하도록 기존 CreateMauiApp 메서드를 수정합니다.

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp(Action<MauiAppBuilder>? additional = null) =>
            CreateMauiApp<App>(additional);
    
        public static MauiApp CreateMauiApp<TApp>(Action<MauiAppBuilder>? additional = null) where TApp : App
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<TApp>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });
    
    #if DEBUG
            builder.Logging.AddDebug();
    #endif
            additional?.Invoke(builder);
    
            return builder.Build();
        }
    }
    
  2. .NET MAUI UI가 포함된 프로젝트에서 각 리소스 사전을 독립 실행형 XAML 파일에서 코드 숨김 파일로 지원되는 리소스 사전으로 변환합니다.

  3. .NET MAUI UI가 포함된 프로젝트에서 일반적으로 App.xaml에서 리소스 사전 인스턴스화를 업데이트하여 Source 속성이 리소스 사전을 포함하는 어셈블리도 지정합니다.

    <ResourceDictionary Source="Resources/Styles/Colors.xaml;assembly=NativeEmbeddingDemo" />
    <ResourceDictionary Source="Resources/Styles/Styles.xaml;assembly=NativeEmbeddingDemo" />
    
  4. 새 .NET MAUI 앱을 만들고 .NET MAUI UI 프로젝트 및 네이티브 포함된 앱이 포함된 솔루션에 추가합니다.

  5. .NET MAUI 앱 프로젝트에서 .NET MAUI UI가 포함된 프로젝트에 대한 참조를 추가합니다.

  6. .NET MAUI 앱 프로젝트에서 .NET MAUI UI 프로젝트에서 리소스를 제공하는 리소스 자식 폴더를 삭제 합니다. 예를 들어 .NET MAUI UI 프로젝트에 리소스 > 글꼴, 리소스 이미지리소스 > > 스타일 폴더가 포함된 경우 방금 만든 .NET MAUI 앱에서 이러한 폴더를 삭제해야 합니다. 이렇게 하면 .NET MAUI 앱이 .NET MAUI UI를 포함하는 프로젝트의 리소스를 사용할 수 있습니다.

  7. .NET MAUI 앱에서 .NET MAUI UI 프로젝트의 클래스에서 App 파생되도록 클래스를 업데이트 App 합니다.

    <myMauiUIProject:App xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                         xmlns:myMauiUIProject="clr-namespace:NativeEmbeddingDemo;assembly=NativeEmbeddingDemo"
                         x:Class="TestHarnessApp.TestApp">
        <myMauiUIProject:App.Resources>
            <!-- App specific resources go here -->
        </myMauiUIProject:App.Resources>
    </myMauiUIProject:App>
    

    그런 다음.NET MAUI UI 프로젝트의 클래스에서 App 파생되고 이 프로젝트에서 모든 XAML 리소스를 로드할 수 있도록 클래스에 대한 App 코드 숨김 파일을 업데이트합니다.

    public partial class TestApp : myMauiUIProject.App
    {
        public TestApp()
        {
            var baseResources = Resources;
            InitializeComponent();
            Resources.MergedDictionaries.Add(baseResources);
            MainPage = new HostPage();
        }
    }
    
  8. .NET MAUI 앱에서 .NET MAUI UI를 포함하는 프로젝트의 UI를 표시하는 페이지를 추가합니다.

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:myMauiUIProject="clr-namespace:NativeEmbeddingDemo;assembly=NativeEmbeddingDemo"
                 x:Class="TestHarnessApp.HostPage"
                 Title="HostPage">
        <myMauiUIProject:MyMauiContent />
    </ContentPage>
    
  9. .NET MAUI 앱에서 .NET MAUI UI를 포함하는 프로젝트에서 메서드를 호출 CreateMauiApp 하도록 클래스를 업데이트 MauiProgram 합니다.

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp() =>
            NativeEmbeddingDemo.MauiProgram.CreateMauiApp<TestApp>(builder =>
            {
                // Add any test harness configuration such as service stubs or mocks.
            });
    }
    

이제 각 플랫폼에서 .NET MAUI 앱 프로젝트를 실행하고 XAML 핫 다시 로드를 사용하여 .NET MAUI UI를 반복할 수 있습니다.

이 방법의 예제는 샘플 앱을 참조 하세요.