Compartilhar via


Incorporação nativa

Procurar exemplo. Procurar no exemplo

Normalmente, um aplicativo do .NET Multi-platform App UI (.NET MAUI) inclui páginas que contêm layouts, como Grid, e layouts que contêm exibições, como Button. Páginas, layouts e exibições derivam de Element. A inserção nativa permite que os controles do .NET MAUI que derivam de Element sejam consumidos em aplicativos nativos .NET para Android, .NET para iOS, .NET para Mac Catalyst e WinUI.

O processo de consumo de um controle MAUI DO .NET em um aplicativo nativo se dá da seguinte forma:

  1. Crie métodos de extensão para inicializar seu aplicativo nativo inserido. Para obter mais informações, consulte Criar métodos de extensão.
  2. Crie um único projeto do MAUI do .NET que contenha sua interface do usuário do MAUI do .NET e quaisquer dependências. Para obter mais informações, consulte Criar um projeto único do MAUI do .NET.
  3. Crie um aplicativo nativo e habilite o suporte ao MAUI do .NET nele. Para obter mais informações, consulte a Política de suporte do MAUI do .NET.
  4. Inicialize o .NET MAUI em seu projeto de aplicativo nativo. Para obter mais informações, consulte Inicializar o MAUI do .NET.
  5. Crie a interface de usuário do MAUI do .NET e converta-a no tipo nativo apropriado com o método de extensão ToPlatformEmbedding. Para obter mais informações, consulte Consumir os controles do MAUI do .NET.
  1. Crie um único projeto do MAUI do .NET que contenha sua interface do usuário do MAUI do .NET e quaisquer dependências. Para obter mais informações, consulte Criar um projeto único do MAUI do .NET.
  2. Crie um aplicativo nativo e habilite o suporte ao MAUI do .NET nele. Para obter mais informações, consulte a Política de suporte do MAUI do .NET.
  3. Inicialize o .NET MAUI em seu projeto de aplicativo nativo. Para obter mais informações, consulte Inicializar o MAUI do .NET.
  4. Crie a interface de usuário do MAUI do .NET e converta-a no tipo nativo apropriado com o método de extensão ToPlatformEmbedding. Para obter mais informações, consulte Consumir os controles do MAUI do .NET.

Observação

Ao usar a inserção nativa, o mecanismo de associação de dados do MAUI do .NET ainda funciona. Porém, a navegação de página deve ser executada usando a API de navegação nativa.

Criar métodos de extensão

Antes de criar um aplicativo nativo que consome os controles do MAUI do .NET, primeiro você deve criar um projeto de biblioteca de classes do MAUI do .NET e excluir a pasta Plataformas e a classe Class1 dele. Em seguida, adicione uma classe a ela chamada EmbeddedExtensions que contém o seguinte código:

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>();
    }
}

Esses métodos de extensão localizam-se no namespace Microsoft.Maui.Controls e são usados para inicializar seu aplicativo nativo inserido em cada plataforma. Os métodos de extensão referenciam os tipos EmbeddedPlatformApplication, EmbeddedWindowHandlere EmbeddedWindowProvider que você também deve adicionar ao projeto de biblioteca do MAUI do .NET.

O código a seguir mostra a classe EmbeddedPlatformApplication, que deve ser adicionada ao mesmo projeto de biblioteca do MAUI do .NET que a classe 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);
    }
}

O código a seguir mostra a classe EmbeddedWindowHandler, que deve ser adicionada ao mesmo projeto de biblioteca do MAUI do .NET que a classe 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.");
}

O código a seguir mostra a classe EmbeddedWindowProvider, que deve ser adicionada ao mesmo projeto de biblioteca do MAUI do .NET que a classe 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;
}

Criar um projeto único do MAUI do .NET

Antes de criar um aplicativo nativo que consome os controles do MAUI do .NET, você deve adicionar um projeto de aplicativo do MAUI do .NET à mesma solução que o projeto de biblioteca de classes do MAUI do .NET criado anteriormente. O projeto de aplicativo do MAUI do .NET armazenará a interface do usuário que você pretende reusar no seu aplicativo nativo inserido. Depois de adicionar um novo projeto de aplicativo do MAUI do .NET à solução, execute as seguintes etapas:

  1. Exclua a pasta Propriedades do projeto.

  2. Exclua a pasta Plataformas do projeto.

  3. Exclua a pasta Recursos/AppIcon do projeto.

  4. Exclua a pasta Recursos/bruto do projeto.

  5. Exclua a pasta Recursos/Splash do projeto.

  6. Exclua a classe AppShell do projeto.

  7. Verifique se a App classe não define a MainPage propriedade ou substitui o CreateWindow método:

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. Exclua a classe MainPage do projeto.

  9. Modifique o arquivo do projeto para que a propriedade de compilação $(TargetFramework) seja definida como net8.0, e a propriedade de compilação $(OutputType) seja removida:

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

    Importante

    Certifique-se de definir a propriedade $(TargetFramework) build, não a propriedade$(TargetFrameworks) build.

  10. Modifique o método CreateMauiApp na classe MauiProgram para que ele aceite um argumento Action<MauiAppBuilder> opcional que é invocado antes que o método retorne:

    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();
    }
    

Neste ponto, você deve adicionar a interface do usuário do MAUI do .NET necessária ao projeto, incluindo dependências e recursos, e garantir que o projeto seja compilado corretamente.

Criar um projeto único do MAUI do .NET

Antes de criar um aplicativo nativo que consome os controles do MAUI do .NET, você deve adicionar um projeto de aplicativo do MAUI do .NET à mesma solução que o projeto de biblioteca de classes do MAUI do .NET criado anteriormente. O projeto de aplicativo do MAUI do .NET armazenará a interface do usuário que você pretende reusar no seu aplicativo nativo inserido. Depois de adicionar um novo projeto de aplicativo do MAUI do .NET à solução, execute as seguintes etapas:

  1. Exclua a pasta Propriedades do projeto.

  2. Exclua a pasta Plataformas do projeto.

  3. Exclua a pasta Recursos/AppIcon do projeto.

  4. Exclua a pasta Recursos/bruto do projeto.

  5. Exclua a pasta Recursos/Splash do projeto.

  6. Exclua a classe AppShell do projeto.

  7. Verifique se a App classe não define a MainPage propriedade ou substitui o CreateWindow método:

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. Exclua a classe MainPage do projeto.

  9. Modifique o arquivo do projeto para que a propriedade de compilação $(TargetFramework) seja definida como net9.0, e a propriedade de compilação $(OutputType) seja removida:

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

    Importante

    Certifique-se de definir a propriedade $(TargetFramework) build, não a propriedade$(TargetFrameworks) build.

  10. MauiProgram Na classe, modifique o CreateMauiApp método para aceitar um TApp argumento genérico e aceite um argumento opcional Action<MauiAppBuilder> que é invocado antes que o método retorne. Além disso, altere a chamada de UseMauiApp<App> para 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 Na classe, adicione uma CreateMauiApp sobrecarga que aceite um argumento opcionalAction<MauiAppBuilder>:

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

Em seguida, você deve adicionar a interface do usuário do .NET MAUI necessária ao projeto, incluindo quaisquer dependências e recursos, e garantir que o projeto seja compilado corretamente.

Habilitar o suporte ao MAUI do .NET

Para consumir controles do .NET MAUI que derivam de Element em um aplicativo .NET para Android, .NET para iOS, .NET para Mac Catalyst ou WinUI, adicione seu projeto de aplicativo nativo à mesma solução do projeto de biblioteca de classes .NET MAUI criado anteriormente. Em seguida, você deve habilitar o suporte ao MAUI do .NET no arquivo de projeto do aplicativo nativo definindo as propriedades de compilação $(UseMaui) e $(MauiEnablePlatformUsings) para true no primeiro nó <PropertyGroup> no arquivo de projeto:

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

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

Quanto aos aplicativos .NET para Mac Catalyst, você também precisará definir a propriedade de build $(SupportedOSPlatformVersion) como, no mínimo, 14.0:

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

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

Para aplicativos .NET para Mac Catalyst, você também precisará definir a $(SupportedOSPlatformVersion) propriedade build como um mínimo de 15.0:

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

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

Quanto aos aplicativos WinUI, você também precisará definir a propriedade de compilação $(EnableDefaultXamlItems) como false:

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

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

Isso impedirá que você receba erros de compilação sobre o método InitializeComponent que já está sendo definido.

Em seguida, adicione os itens de compilação $(PackageReference) ao arquivo de projeto nos pacotes NuGet Microsoft.Maui.Controls e Microsoft.Maui.Controls.Compatiblity:

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

Em seguida, adicione $(PackageReference) itens de build ao arquivo de projeto para o Microsoft.Maui.Controls pacote NuGet:

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

Inicializar o MAUI do .NET

O MAUI do .NET deve ser inicializado antes que um projeto de aplicativo nativo possa construir um controle do MAUI do .NET. Escolher quando inicializá-lo depende principalmente de quando ele é mais conveniente no fluxo do aplicativo – ele pode ser executado na inicialização ou pouco antes de um controle do MAUI do .NET ser construído. A abordagem descrita aqui é inicializar o MAUI do .NET quando a interface do usuário inicial do aplicativo é criada.

Normalmente, o padrão para inicializar o MAUI do .NET em um projeto de aplicativo nativo se dá da seguinte forma:

No Android, a substituição OnCreate na classe MainActivity normalmente é o local para executar tarefas relacionadas à inicialização do aplicativo. O exemplo de código a seguir mostra o MAUI do .NET sendo inicializado na classe 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

        ...              
    }
}

No iOS e no Mac Catalyst, a classe AppDelegate deve ser modificada para retornar true para a substituição 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;
}

O método WillConnect na classe SceneDelegate deve então ser modificado para criar seu controlador de visualização principal e defini-lo como a visualização do 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();
    }

    ...
}

Em seguida, no editor XML, abra o arquivo Info.plist e adicione o seguinte XML ao final do arquivo:

<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>

O MAUI do .NET pode ser inicializado no método ViewDidLoad no seu controlador de exibição principal:

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

        ...
    }
}

No Windows, a classe MainWindow normalmente é o local para executar as tarefas de inicialização de aplicativo relacionadas à interface do usuário:

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

        ...
    }
}

Neste exemplo, o objeto MauiApp é criado usando a inicialização lenta. O método de extensão UseMauiEmbedding é invocado no objeto MauiAppBuilder. Portanto, seu projeto de aplicativo nativo deve incluir uma referência ao projeto de biblioteca de classes do MAUI do .NET que você criou contendo esse método de extensão. Assim, um objeto MauiContext é criado no objeto MauiApp, com um determinando bool, do local de onde o contexto tem escopo. O objeto MauiContext será usado ao converter controles os MAUI do .NET nos tipos nativos.

A inserção pode ser executada em um contexto de aplicativo ou em um contexto de janela, mas para compatibilidade máxima com o .NET MAUI, ela deve ser executada em um contexto de janela.

Contexto do aplicativo

A inserção nativa pode ser executada em um contexto de aplicativo, em que o aplicativo nativo não tem conhecimento de uma janela. Com essa abordagem, a inicialização de incorporação nativa exige que você:

O exemplo a seguir mostra essa abordagem:

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

Uma exibição .NET MAUI pode ser criada e convertida em uma exibição nativa com o ToPlatformEmbedded método de extensão, que requer o MauiContext objeto como um argumento.

Essa abordagem é adequada para cenários em que um aplicativo nativo precisa inserir uma interface do usuário simples do .NET MAUI, mas não requer acesso a todos os recursos do .NET MAUI. A desvantagem dessa abordagem é que ferramentas, como recarga dinâmica e alguns recursos do .NET MAUI, não funcionarão.

Dica

Não é recomendável criar um MauiApp objeto sempre que uma exibição .NET MAUI é inserida como uma exibição nativa. Isso pode ser problemático se as exibições inseridas acessarem a Application.Current propriedade. Em vez disso, o MauiApp objeto pode ser criado como uma instância estática compartilhada:

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

Com essa abordagem, você pode instanciar o objeto no início do ciclo de vida do MauiApp aplicativo para evitar um pequeno atraso na primeira vez que inserir uma exibição .NET MAUI em seu aplicativo.

No Android, um fragmento representa uma parte da IU em uma atividade. O exemplo de código a seguir mostra o .NET MAUI sendo inicializado em um fragmento:

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);

        ...
    }
}

No iOS e no Mac Catalyst, a classe AppDelegate deve ser modificada para retornar true para a substituição 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;
}

O método WillConnect na classe SceneDelegate deve então ser modificado para criar seu controlador de visualização principal e defini-lo como a visualização do 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();
    }

    ...
}

Em seguida, no editor XML, abra o arquivo Info.plist e adicione o seguinte XML ao final do arquivo:

<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>

O MAUI do .NET pode ser inicializado no método ViewDidLoad no seu controlador de exibição principal:

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);

        ...
    }
}

No Windows, a classe MainWindow normalmente é o local para executar as tarefas de inicialização de aplicativo relacionadas à interface do usuário:

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);

        ...
    }
}

Neste exemplo, o MauiApp objeto é criado como uma instância estática compartilhada. Quando esse objeto é criado, é chamado que, por sua vez, MauiProgram.CreateMauiApp chama o UseMauiEmbedding método de extensão no MauiAppBuilder objeto. Portanto, seu projeto de aplicativo nativo deve incluir uma referência ao projeto de biblioteca de classes .NET MAUI que você criou que contém sua MauiProgram classe e sua interface do usuário do .NET MAUI. Um MauiContext objeto é então criado a partir do MauiApp objeto, que tem como escopo o MauiApp objeto. O objeto MauiContext será usado ao converter controles os MAUI do .NET nos tipos nativos.

Contexto da janela

A inserção nativa pode ser executada em um contexto de janela, em que o aplicativo nativo tem conhecimento de uma janela. Em alguns cenários, as exibições do .NET MAUI exigem acesso a uma janela para funcionar corretamente. Por exemplo, os gatilhos adaptáveis exigem acesso à janela de uma exibição e, se não houver janela, eles não funcionam.

Com essa abordagem, a inicialização de incorporação nativa exige que você:

  • Crie um objeto MauiApp.
  • Crie um MauiContext objeto com o CreateEmbeddedWindowContext método. O MauiContext objeto será usado para obter uma exibição nativa da exibição MAUI do .NET.

O CreateEmbeddedWindowContext método cria um contexto de janela que relaciona uma janela nativa a uma janela MAUI do .NET:

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

Uma exibição .NET MAUI pode ser criada e convertida em uma exibição nativa com o ToPlatformEmbedded método de extensão, que requer o MauiContext objeto como um argumento.

Observação

O ToPlatformEmbedded método de extensão tem uma sobrecarga que adiciona uma exibição .NET MAUI a uma janela inserida.

A vantagem dessa abordagem é que há uma única janela .NET MAUI para cada janela nativa, as APIs relacionadas à janela funcionarão corretamente e as ferramentas, como recarga dinâmica, funcionarão corretamente.

Dica

Não é recomendável criar um MauiApp objeto sempre que uma exibição .NET MAUI é inserida como uma exibição nativa. Isso pode ser problemático se as exibições inseridas acessarem a Application.Current propriedade. Em vez disso, o MauiApp objeto pode ser criado como uma instância estática compartilhada:

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

Com essa abordagem, você pode instanciar o objeto no início do ciclo de vida do MauiApp aplicativo para evitar um pequeno atraso na primeira vez que inserir uma exibição .NET MAUI em seu aplicativo.

No Android, um fragmento representa uma parte da IU em uma atividade. O exemplo de código a seguir mostra o .NET MAUI sendo inicializado em um fragmento:

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;

        ...
    }
}

No iOS e no Mac Catalyst, a classe AppDelegate deve ser modificada para retornar true para a substituição 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;
}

O método WillConnect na classe SceneDelegate deve então ser modificado para criar seu controlador de visualização principal e defini-lo como a visualização do 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();
    }

    ...
}

Em seguida, no editor XML, abra o arquivo Info.plist e adicione o seguinte XML ao final do arquivo:

<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>

O MAUI do .NET pode ser inicializado no método ViewDidLoad no seu controlador de exibição principal:

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;

        ...
    }
}

No Windows, a classe MainWindow normalmente é o local para executar as tarefas de inicialização de aplicativo relacionadas à interface do usuário:

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;

        ...
    }
}

Neste exemplo, o MauiApp objeto é criado como uma instância estática compartilhada. Quando esse objeto é criado, é chamado que, por sua vez, MauiProgram.CreateMauiApp chama o UseMauiEmbedding método de extensão no MauiAppBuilder objeto. Portanto, seu projeto de aplicativo nativo deve incluir uma referência ao projeto de biblioteca de classes .NET MAUI que você criou que contém sua MauiProgram classe e sua interface do usuário do .NET MAUI. Em seguida, um MauiContext objeto é criado com o CreateEmbeddedWindowContext método, que tem como escopo a janela. O objeto MauiContext será usado ao converter controles os MAUI do .NET nos tipos nativos.

Consumir os controles do MAUI do .NET

Depois que o MAUI do .NET tiver sido inicializado no seu aplicativo nativo, você poderá adicionar a interface do usuário do MAUI do .NET ao layout do aplicativo nativo. Isso pode ser feito criando uma instância da interface do usuário e convertendo-a no tipo nativo apropriado com o método de extensão ToPlatformEmbedded.

No Android, o método de extensão ToPlatformEmbedded converte o controle do MAUI do .NET em um objeto Android View:

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

Neste exemplo, um objeto derivado de ContentView é convertido em um objeto Android View.

Observação

O método de extensão ToPlatformEmbedded se localiza na biblioteca de classes do MAUI do .NET que você criou anteriormente. Por isso, seu projeto de aplicativo nativo deve incluir uma referência a esse projeto.

Observação

O ToPlatformEmbedded método de extensão está no Microsoft.Maui.Controls.Embedding namespace. Portanto, seu projeto de aplicativo nativo deve incluir uma using instrução para esse namespace.

O objeto View pode ser adicionado a um layout no seu aplicativo nativo:

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

No iOS e no Mac Catalyst, o método de extensão ToPlatformEmbedded converte o controle do MAUI do .NET em um objeto UIView:

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

Nesse exemplo, um objeto derivado de ContentView-é convertido em um objeto UIView e, em seguida, restrições de largura e altura são definidas nele para permitir a interação.

Observação

O método de extensão ToPlatformEmbedded se localiza na biblioteca de classes do MAUI do .NET que você criou anteriormente. Por isso, seu projeto de aplicativo nativo deve incluir uma referência a esse projeto.

O objeto UIView pode ser adicionado a uma exibição no controlador de exibição:

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

Neste exemplo, um objeto derivado de ContentView é convertido em um objeto UIView.

Observação

O ToPlatformEmbedded método de extensão está no Microsoft.Maui.Controls.Embedding namespace. Portanto, seu projeto de aplicativo nativo deve incluir uma using instrução para esse namespace.

O objeto UIView pode ser adicionado a uma exibição no controlador de exibição:

stackView.AddArrangedSubView(new ContainerView(nativeView));

ContainerView é um tipo personalizado que encapsula a exibição MAUI do .NET para garantir que ela seja dimensionada corretamente. Isso é feito redirecionando IntrinsicContentSize para a exibição .NET MAUI: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();
    }
}

Além disso, um ToUIViewController método de extensão no .NET MAUI pode ser usado para converter uma página .NET MAUI em um UIViewController:

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

Neste exemplo, um objeto derivado de ContentPage é convertido em um UIViewController.

No Windows, o método de extensão ToPlatformEmbedded converte o controle do MAUI do .NET em um objeto FrameworkElement:

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

Neste exemplo, um objeto derivado de ContentView é convertido em um objeto FrameworkElement. O objeto FrameworkElement pode ser definido como o conteúdo de uma página WinUI.

Observação

O método de extensão ToPlatformEmbedded se localiza na biblioteca de classes do MAUI do .NET que você criou anteriormente. Por isso, seu projeto de aplicativo nativo deve incluir uma referência a esse projeto.

Observação

O ToPlatformEmbedded método de extensão está no Microsoft.Maui.Controls.Embedding namespace. Portanto, seu projeto de aplicativo nativo deve incluir uma using instrução para esse namespace.

O objeto FrameworkElement pode ser adicionado a um layout no seu aplicativo nativo:

stackPanel.Children.Add(nativeView);

Importante

Para evitar que ocorra um erro, o recarregamento dinâmico XAML deve ser desabilitado antes de executar um aplicativo nativo inserido na configuração de depuração.

Suporte à Recarga Dinâmica de XAML

Não há suporte para a Recarga Dinâmica de XAML em aplicativos nativos inseridos. No entanto, você ainda pode usar a Recarga Dinâmica de XAML para iterar rapidamente sobre sua interface do usuário .NET MAUI, criando um aplicativo .NET MAUI que consuma a interface do usuário .NET MAUI.

Para exibir a interface do usuário .NET MAUI com Recarga Dinâmica de XAML:

  1. No projeto que contém sua interface do usuário .NET MAUI, atualize a classe MauiProgram para adicionar um método de sobrecarga CreateMauiApp e modifique o método CreateMauiApp existente para aceitar um argumento genérico:

    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. No projeto que contém sua interface do usuário .NET MAUI, converta cada dicionário de recursos de um arquivo XAML independente para um dicionário de recursos que seja apoiado por um arquivo de código por trás.

  3. No projeto que contém sua interface do usuário .NET MAUI, atualize a instância do seu dicionário de recursos, geralmente em App.xaml, para que a propriedade Source também especifique o assembly que contém o dicionário de recursos:

    <ResourceDictionary Source="Resources/Styles/Colors.xaml;assembly=NativeEmbeddingDemo" />
    <ResourceDictionary Source="Resources/Styles/Styles.xaml;assembly=NativeEmbeddingDemo" />
    
  4. Crie um novo aplicativo .NET MAUI e adicione-o à solução que contém seu projeto de interface do usuário .NET MAUI e aplicativos nativos inseridos.

  5. No projeto do seu aplicativo .NET MAUI, adicione uma referência ao projeto que contém sua interface do usuário .NET MAUI.

  6. No projeto do seu aplicativo .NET MAUI, exclua quaisquer pastas filhas Resource onde o recurso é fornecido pelo projeto da sua interface do usuário .NET MAUI. Por exemplo, se o projeto da interface do usuário .NET MAUI contém as pastas Resources > Fonts, Resources > Images e Resources > Styles, essas pastas devem ser excluídas do aplicativo .NET MAUI que você acabou de criar. Isso permite que seu aplicativo .NET MAUI consuma os recursos do projeto que contém sua interface do usuário .NET MAUI.

  7. No seu aplicativo .NET MAUI, atualize a classe App para que ela herde da classe App no seu projeto de interface do usuário .NET MAUI:

    <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>
    

    Em seguida, atualize o arquivo de código por trás da classe App para que ele herde da classe App no seu projeto de interface do usuário .NET MAUI e carregue quaisquer recursos XAML deste projeto:

    public partial class TestApp : myMauiUIProject.App
    {
        public TestApp()
        {
            var baseResources = Resources;
            InitializeComponent();
            Resources.MergedDictionaries.Add(baseResources);
            MainPage = new HostPage();
        }
    }
    
  8. No seu aplicativo .NET MAUI, adicione uma página que exiba a interface do usuário do projeto que contém sua interface do usuário .NET MAUI:

    <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. No seu aplicativo .NET MAUI, atualize a classe MauiProgram para chamar o método CreateMauiApp no projeto que contém sua interface do usuário .NET MAUI:

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

Agora você deve ser capaz de executar o projeto do seu aplicativo .NET MAUI em cada plataforma e usar a Recarga Dinâmica de XAML para iterar sobre a sua interface do usuário .NET MAUI.

Para obter um exemplo dessa abordagem, consulte o aplicativo de exemplo.