Compartir a través de


Inserción nativa

Examinar ejemplo. Examinar el ejemplo

Normalmente, una aplicación de.NET Multi-platform App UI (.NET MAUI) incluye páginas que contienen diseños, como Grid, y diseños que contienen vistas, como Button. Las páginas, los diseños y las vistas se derivan de la clase Element. La inserción nativa permite que cualquier control de .NET MAUI que derive de Element se consuma en aplicaciones nativas de .NET para Android, .NET para iOS, .NET para Mac Catalyst y WinUI.

El proceso para consumir un control .NET MAUI en una aplicación nativa es el siguiente:

  1. Cree métodos de extensión para arrancar la aplicación insertada nativa. Para obtener más información, consulte Crear métodos de extensión.
  2. Cree un proyecto único de .NET MAUI que contenga la interfaz de usuario de .NET MAUI y las dependencias. Para obtener más información, consulte Creación de un proyecto único de .NET MAUI.
  3. Cree una aplicación nativa y habilite la compatibilidad con .NET MAUI en ella. Para obtener más información, consulte Habilitación de la compatibilidad con .NET MAUI.
  4. Inicialice .NET MAUI en el proyecto de aplicación nativa. Para obtener más información, consulte Initialize .NET MAUI(Inicializar .NET MAUI).
  5. Cree la interfaz de usuario de MAUI de .NET y conviértala en el tipo nativo adecuado con el método de extensión ToPlatformEmbedding. Para obtener más información, consulte Consumo de controles MAUI de .NET.
  1. Cree un proyecto único de .NET MAUI que contenga la interfaz de usuario de .NET MAUI y las dependencias. Para obtener más información, consulte Creación de un proyecto único de .NET MAUI.
  2. Cree una aplicación nativa y habilite la compatibilidad con .NET MAUI en ella. Para obtener más información, consulte Habilitación de la compatibilidad con .NET MAUI.
  3. Inicialice .NET MAUI en el proyecto de aplicación nativa. Para obtener más información, consulte Initialize .NET MAUI(Inicializar .NET MAUI).
  4. Cree la interfaz de usuario de MAUI de .NET y conviértala en el tipo nativo adecuado con el método de extensión ToPlatformEmbedding. Para obtener más información, consulte Consumo de controles MAUI de .NET.

Nota:

Al usar la inserción nativa, el motor de enlace de datos de .NET MAUI sigue funcionando. Sin embargo, la navegación de páginas debe realizarse mediante la API de navegación nativa.

Creación de métodos de extensión

Antes de crear una aplicación nativa que consuma controles MAUI de .NET, primero debe crear un proyecto de biblioteca de clases .NET MAUI y eliminar la carpeta Platforms y la clase Class1 de ella. A continuación, agregue una clase a ella denominada EmbeddedExtensions que contenga el código siguiente:

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

Estos métodos de extensión están en el espacio de nombres Microsoft.Maui.Controls y se usan para arrancar la aplicación insertada nativa en cada plataforma. Los métodos de extensión hacen referencia a los tipos EmbeddedPlatformApplication, EmbeddedWindowHandler, y EmbeddedWindowProvider que también debe agregar al proyecto de biblioteca MAUI de .NET.

El código siguiente muestra la clase EmbeddedPlatformApplication, que se debe agregar al mismo proyecto de biblioteca MAUI de .NET que la clase 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);
    }
}

El código siguiente muestra la clase EmbeddedWindowHandler, que se debe agregar al mismo proyecto de biblioteca MAUI de .NET que la clase 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.");
}

El código siguiente muestra la clase EmbeddedWindowProvider, que se debe agregar al mismo proyecto de biblioteca MAUI de .NET que la clase 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;
}

Creación de un proyecto único de MAUI de .NET

Antes de crear una aplicación nativa que consuma controles MAUI de .NET, debe agregar un proyecto de aplicación MAUI de .NET a la misma solución que el proyecto de biblioteca de clases MAUI de .NET que ha creado anteriormente. El proyecto de aplicación MAUI de .NET almacenará la interfaz de usuario que quiere volver a usar en la aplicación insertada nativa. Después de agregar un nuevo proyecto de aplicación MAUI de .NET a la solución, realice los pasos siguientes:

  1. Elimine la carpeta Propiedades del proyecto.

  2. Elimine la carpeta Plataforma del proyecto.

  3. Elimine la carpeta Resources/AppIcon del proyecto.

  4. Elimine la carpeta Resources/raw del proyecto.

  5. Elimine la carpetaResources/Splash del proyecto.

  6. Elimine la clase AppShell del proyecto.

  7. Asegúrese de que la App clase no establece la MainPage propiedad ni invalida el CreateWindow método :

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. Elimine la clase MainPage del proyecto.

  9. Modifique el archivo de proyecto para que la propiedad de compilación $(TargetFramework) esté establecida en net8.0 y se quite la propiedad de compilación $(OutputType) :

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

    Importante

    Asegúrese de establecer la propiedad de compilación $(TargetFramework) y no la propiedad de compilación $(TargetFrameworks).

  10. Modifique el método CreateMauiApp de la clase MauiProgram para que acepte un argumento opcional Action<MauiAppBuilder> que se invoca antes de que el método devuelva:

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

En este punto, debe agregar la interfaz de usuario de .NET MAUI necesaria al proyecto, incluidas las dependencias y los recursos, y asegurarse de que el proyecto se compila correctamente.

Creación de un proyecto único de MAUI de .NET

Antes de crear una aplicación nativa que consuma controles MAUI de .NET, debe agregar un proyecto de aplicación MAUI de .NET a la misma solución que el proyecto de biblioteca de clases MAUI de .NET que ha creado anteriormente. El proyecto de aplicación MAUI de .NET almacenará la interfaz de usuario que quiere volver a usar en la aplicación insertada nativa. Después de agregar un nuevo proyecto de aplicación MAUI de .NET a la solución, realice los pasos siguientes:

  1. Elimine la carpeta Propiedades del proyecto.

  2. Elimine la carpeta Plataforma del proyecto.

  3. Elimine la carpeta Resources/AppIcon del proyecto.

  4. Elimine la carpeta Resources/raw del proyecto.

  5. Elimine la carpetaResources/Splash del proyecto.

  6. Elimine la clase AppShell del proyecto.

  7. Asegúrese de que la App clase no establece la MainPage propiedad ni invalida el CreateWindow método :

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  8. Elimine la clase MainPage del proyecto.

  9. Modifique el archivo de proyecto para que la propiedad de compilación $(TargetFramework) esté establecida en net9.0 y se quite la propiedad de compilación $(OutputType) :

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

    Importante

    Asegúrese de establecer la propiedad de compilación $(TargetFramework) y no la propiedad de compilación $(TargetFrameworks).

  10. En la MauiProgram clase , modifique el CreateMauiApp método para aceptar un TApp argumento genérico y acepte un argumento opcional Action<MauiAppBuilder> que se invoca antes de que el método devuelva. Además, cambie la llamada de UseMauiApp<App> a 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. En la MauiProgram clase , agregue una CreateMauiApp sobrecarga que acepte un argumento opcional Action<MauiAppBuilder> :

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

A continuación, debe agregar la interfaz de usuario de .NET MAUI necesaria al proyecto, incluidas las dependencias y los recursos, y asegurarse de que el proyecto se compila correctamente.

Habilitación de la compatibilidad con .NET MAUI

Para consumir controles de .NET MAUI que deriven de Element en una aplicación .NET para Android, .NET para iOS, .NET para Mac Catalyst o WinUI, deberá agregar el proyecto de su aplicación nativa a la misma solución que el proyecto de biblioteca de clases de .NET MAUI que creó anteriormente. A continuación, debe habilitar la compatibilidad con MAUI de .NET en el archivo de proyecto de la aplicación nativa estableciendo las propiedades de compilación $(UseMaui) y $(MauiEnablePlatformUsings) en true el primer nodo <PropertyGroup> del archivo de proyecto:

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

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

En el caso de las aplicaciones .NET para Mac Catalyst, también deberá establecer la propiedad de compilación $(SupportedOSPlatformVersion) en 14.0 como mínimo:

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

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

Para las aplicaciones .NET para Mac Catalyst, también deberá establecer la $(SupportedOSPlatformVersion) propiedad build en un mínimo de 15.0:

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

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

En el caso de las aplicaciones WinUI, también deberá establecer la propiedad de compilación $(EnableDefaultXamlItems) en false:

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

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

Esto dejará de recibir errores de compilación sobre el método InitializeComponent que ya se está definiendo.

A continuación, agregue elementos de compilación $(PackageReference) al archivo de proyecto para los paquetes NuGet Microsoft.Maui.Controls y Microsoft.Maui.Controls.Compatiblity:

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

A continuación, agregue $(PackageReference) elementos de compilación al archivo de proyecto para el Microsoft.Maui.Controls paquete NuGet:

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

Inicializar .NET MAUI

.NET MAUI debe inicializarse antes de que un proyecto de aplicación nativa pueda construir un control .NET MAUI. Elegir cuándo inicializarlo depende principalmente de cuándo es más conveniente en el flujo de la aplicación: se puede realizar en el inicio o justo antes de que se construya un control MAUI de .NET. El enfoque descrito aquí es inicializar .NET MAUI cuando se crea la interfaz de usuario inicial de la aplicación.

Normalmente, el patrón para inicializar .NET MAUI en un proyecto de aplicación nativa es el siguiente:

En Android, la invalidación OnCreate de la clase MainActivity suele ser el lugar para realizar tareas relacionadas con el inicio de la aplicación. En el ejemplo de código siguiente se muestra que se inicializa .NET MAUI en la clase 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

        ...              
    }
}

En iOS y Mac Catalyst, la clase AppDelegate debería modificarse para devolver true para la invalidación 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;
}

Después debería modificarse el método WillConnect de la clase SceneDelegate para crear su controlador de vista principal y establecerlo como vista de la clase 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();
    }

    ...
}

Después, en el editor XML, abra el archivo Info.plist y agregue el siguiente XML al final del archivo:

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

A continuación, se puede inicializar .NET MAUI en el método ViewDidLoad en el controlador de vista 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

        ...
    }
}

En Windows, la clase MainWindow suele ser el lugar para realizar tareas de inicio de aplicaciones relacionadas con la interfaz de usuario:

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

        ...
    }
}

En este ejemplo, el objeto MauiApp se crea mediante la inicialización diferida. El método de extensión UseMauiEmbedding se invoca en el objeto MauiAppBuilder. Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia al proyecto de biblioteca de clases MAUI de .NET que ha creado lo que contiene este método de extensión. A continuación, se crea un objeto MauiContext a partir del objeto MauiApp, con un bool determinando desde dónde se limita el contexto. El objeto MauiContext se usará al convertir controles .NET MAUI a tipos nativos.

La inserción se puede realizar en un contexto de aplicación o en un contexto de ventana, pero para obtener la compatibilidad máxima de .NET MAUI debe realizarse en un contexto de ventana.

Contexto de la aplicación

La inserción nativa se puede realizar en un contexto de aplicación, donde la aplicación nativa no tiene conocimiento de una ventana. Con este enfoque, la inicialización de inserción nativa requiere que:

En el ejemplo siguiente se muestra este enfoque:

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

A continuación, se puede crear y convertir una vista MAUI de .NET en una vista nativa con el ToPlatformEmbedded método de extensión, que requiere el MauiContext objeto como argumento.

Este enfoque es adecuado para escenarios en los que una aplicación nativa necesita insertar una interfaz de usuario de .NET MAUI simple, pero no requiere acceso a todas las características de .NET MAUI. La desventaja de este enfoque es que las herramientas, como la recarga activa, y algunas características de MAUI de .NET, no funcionarán.

Sugerencia

No se recomienda crear un MauiApp objeto cada vez que se inserta una vista MAUI de .NET como una vista nativa. Esto puede ser problemático si las vistas incrustadas acceden a la Application.Current propiedad . En su lugar, el MauiApp objeto se puede crear como una instancia estática compartida:

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

Con este enfoque, puede crear instancias del MauiApp objeto al principio del ciclo de vida de la aplicación para evitar tener un pequeño retraso la primera vez que inserte una vista MAUI de .NET en la aplicación.

En Android, un fragmento representa una parte de la interfaz de usuario dentro de una actividad. En el ejemplo de código siguiente se muestra que .NET MAUI se inicializa en un 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);

        ...
    }
}

En iOS y Mac Catalyst, la clase AppDelegate debería modificarse para devolver true para la invalidación 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;
}

Después debería modificarse el método WillConnect de la clase SceneDelegate para crear su controlador de vista principal y establecerlo como vista de la clase 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();
    }

    ...
}

Después, en el editor XML, abra el archivo Info.plist y agregue el siguiente XML al final del archivo:

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

A continuación, se puede inicializar .NET MAUI en el método ViewDidLoad en el controlador de vista 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);

        ...
    }
}

En Windows, la clase MainWindow suele ser el lugar para realizar tareas de inicio de aplicaciones relacionadas con la interfaz de usuario:

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

        ...
    }
}

En este ejemplo, el MauiApp objeto se crea como una instancia estática compartida. Cuando se crea este objeto, se llama a que, a su vez, MauiProgram.CreateMauiApp llama al UseMauiEmbedding método de extensión en el MauiAppBuilder objeto . Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia al proyecto de biblioteca de clases MAUI de .NET que creó que contiene la MauiProgram clase y la interfaz de usuario de .NET MAUI. A continuación, se crea un MauiContext objeto a partir del MauiApp objeto , cuyo ámbito es el MauiApp objeto . El objeto MauiContext se usará al convertir controles .NET MAUI a tipos nativos.

Contexto de ventana

La inserción nativa se puede realizar en un contexto de ventana, donde la aplicación nativa tiene conocimiento de una ventana. En algunos escenarios, las vistas MAUI de .NET requieren acceso a una ventana para que funcione correctamente. Por ejemplo, los desencadenadores adaptables requieren acceso a la ventana de una vista y, si no hay ninguna ventana, no funcionan.

Con este enfoque, la inicialización de inserción nativa requiere que:

  • Crear un objeto MauiApp.
  • Cree un MauiContext objeto con el CreateEmbeddedWindowContext método . El MauiContext objeto se usará para obtener una vista nativa de la vista MAUI de .NET.

El CreateEmbeddedWindowContext método crea un contexto de ventana que relaciona una ventana nativa con una ventana MAUI de .NET:

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

A continuación, se puede crear y convertir una vista MAUI de .NET en una vista nativa con el ToPlatformEmbedded método de extensión, que requiere el MauiContext objeto como argumento.

Nota:

El ToPlatformEmbedded método de extensión tiene una sobrecarga que agrega una vista MAUI de .NET a una ventana incrustada.

La ventaja de este enfoque es que hay una sola ventana de .NET MAUI para cada ventana nativa, las API relacionadas con ventanas funcionarán correctamente y las herramientas como la recarga activa funcionan correctamente.

Sugerencia

No se recomienda crear un MauiApp objeto cada vez que se inserta una vista MAUI de .NET como una vista nativa. Esto puede ser problemático si las vistas incrustadas acceden a la Application.Current propiedad . En su lugar, el MauiApp objeto se puede crear como una instancia estática compartida:

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

Con este enfoque, puede crear instancias del MauiApp objeto al principio del ciclo de vida de la aplicación para evitar tener un pequeño retraso la primera vez que inserte una vista MAUI de .NET en la aplicación.

En Android, un fragmento representa una parte de la interfaz de usuario dentro de una actividad. En el ejemplo de código siguiente se muestra que .NET MAUI se inicializa en un 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;

        ...
    }
}

En iOS y Mac Catalyst, la clase AppDelegate debería modificarse para devolver true para la invalidación 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;
}

Después debería modificarse el método WillConnect de la clase SceneDelegate para crear su controlador de vista principal y establecerlo como vista de la clase 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();
    }

    ...
}

Después, en el editor XML, abra el archivo Info.plist y agregue el siguiente XML al final del archivo:

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

A continuación, se puede inicializar .NET MAUI en el método ViewDidLoad en el controlador de vista 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;

        ...
    }
}

En Windows, la clase MainWindow suele ser el lugar para realizar tareas de inicio de aplicaciones relacionadas con la interfaz de usuario:

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;

        ...
    }
}

En este ejemplo, el MauiApp objeto se crea como una instancia estática compartida. Cuando se crea este objeto, se llama a que, a su vez, MauiProgram.CreateMauiApp llama al UseMauiEmbedding método de extensión en el MauiAppBuilder objeto . Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia al proyecto de biblioteca de clases MAUI de .NET que creó que contiene la MauiProgram clase y la interfaz de usuario de .NET MAUI. A continuación, se crea un MauiContext objeto con el CreateEmbeddedWindowContext método , cuyo ámbito es la ventana. El objeto MauiContext se usará al convertir controles .NET MAUI a tipos nativos.

Consumo de controles .NET MAUI

Después de inicializar .NET MAUI en la aplicación nativa, puede agregar la interfaz de usuario de .NET MAUI al diseño de la aplicación nativa. Esto se puede lograr mediante la creación de una instancia de la interfaz de usuario y la conversión al tipo nativo adecuado con el método de extensión ToPlatformEmbedded.

En Android, el método de extensión ToPlatformEmbedded convierte el control MAUI de .NET en un objeto android View:

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

En este ejemplo, un objeto derivado de ContentView se convierte en un objeto View de Android.

Nota:

El método de extensión ToPlatformEmbedded está en la biblioteca de clases MAUI de .NET que creó anteriormente. Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia a ese proyecto.

Nota:

El ToPlatformEmbedded método de extensión está en el Microsoft.Maui.Controls.Embedding espacio de nombres . Por lo tanto, el proyecto de aplicación nativa debe incluir una using instrucción para ese espacio de nombres.

A continuación, el objeto View se puede agregar a un diseño de la aplicación nativa:

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

En iOS y Mac Catalyst, el método de extensión ToPlatformEmbedded convierte el control .NET MAUI en un 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;

En este ejemplo, un objeto derivado de ContentView se convierte en un objeto UIView y después se le establecen restricciones de anchura y altura para permitir la interacción.

Nota:

El método de extensión ToPlatformEmbedded está en la biblioteca de clases MAUI de .NET que creó anteriormente. Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia a ese proyecto.

A continuación, el objeto UIView se puede agregar a una vista en el controlador de vista:

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

En este ejemplo, un objeto derivado de ContentView se convierte en un objeto UIView.

Nota:

El ToPlatformEmbedded método de extensión está en el Microsoft.Maui.Controls.Embedding espacio de nombres . Por lo tanto, el proyecto de aplicación nativa debe incluir una using instrucción para ese espacio de nombres.

A continuación, el objeto UIView se puede agregar a una vista en el controlador de vista:

stackView.AddArrangedSubView(new ContainerView(nativeView));

ContainerView es un tipo personalizado que ajusta la vista MAUI de .NET para asegurarse de que tiene el tamaño correcto. Esto se logra redirigiendo IntrinsicContentSize a la vista MAUI de SizeThatFits.NET :

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

Además, se puede usar un ToUIViewController método de extensión en .NET MAUI para convertir una página .NET MAUI en :UIViewController

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

En este ejemplo, un objeto derivado de ContentPage se convierte en un objeto UIViewController.

En Windows, el método de extensión ToPlatformEmbedded convierte el control MAUI de .NET en un objeto FrameworkElement:

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

En este ejemplo, un objeto derivado de ContentView se convierte en un objeto FrameworkElement. Después, el objeto FrameworkElement se puede definir como el contenido de una página WinUI.

Nota:

El método de extensión ToPlatformEmbedded está en la biblioteca de clases MAUI de .NET que creó anteriormente. Por lo tanto, el proyecto de aplicación nativa debe incluir una referencia a ese proyecto.

Nota:

El ToPlatformEmbedded método de extensión está en el Microsoft.Maui.Controls.Embedding espacio de nombres . Por lo tanto, el proyecto de aplicación nativa debe incluir una using instrucción para ese espacio de nombres.

A continuación, el objeto FrameworkElement se puede agregar a un diseño de la aplicación nativa:

stackPanel.Children.Add(nativeView);

Importante

Para evitar un error, la recarga activa de XAML debe deshabilitarse antes de ejecutar una aplicación insertada nativa en la configuración de depuración.

Compatibilidad con la Recarga activa de XAML

La Recarga activa de XAML no se admite en aplicaciones insertadas nativas. Sin embargo, todavía puede usar la Recarga activa de XAML para iterar rápidamente en la interfaz de usuario de .NET MAUI mediante la creación de una aplicación de .NET MAUI que consuma la interfaz de usuario de .NET MAUI.

Para ver la interfaz de usuario de .NET MAUI con la Recarga activa de XAML:

  1. En el proyecto que contiene la interfaz de usuario de .NET MAUI, actualice la clase MauiProgram para agregar una sobrecarga CreateMauiApp y modifique el método CreateMauiApp existente para aceptar un 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. En el proyecto que contiene la interfaz de usuario de .NET MAUI, convierta cada diccionario de recursos de un archivo XAML independiente en un diccionario de recursos respaldado por un archivo de código subyacente.

  3. En el proyecto que contiene la interfaz de usuario de .NET MAUI, actualice la creación de instancias del diccionario de recursos, normalmente en App.xaml, de modo que la propiedad Source especifique también el ensamblado que contiene el diccionario de recursos:

    <ResourceDictionary Source="Resources/Styles/Colors.xaml;assembly=NativeEmbeddingDemo" />
    <ResourceDictionary Source="Resources/Styles/Styles.xaml;assembly=NativeEmbeddingDemo" />
    
  4. Cree una nueva aplicación de .NET MAUI y agréguela a la solución que contiene el proyecto de la interfaz de usuario de .NET MAUI y las aplicaciones insertadas nativas.

  5. En el proyecto de aplicación de .NET MAUI, agregue una referencia al proyecto que contiene la interfaz de usuario de .NET MAUI.

  6. En el proyecto de la aplicación de .NET MAUI, elimine las carpetas secundarias de recursos en las que el proyecto de la interfaz de usuario de .NET MAUI proporciona el recurso. Por ejemplo, si el proyecto de la interfaz de usuario de .NET MAUI contiene carpetas de Recursos > Fuentes, Recursos > Imágenes y Recursos > Estilos, estas carpetas deben eliminarse de la aplicación de .NET MAUI que acaba de crear. Esto permite que la aplicación de .NET MAUI consuma los recursos del proyecto que contiene la interfaz de usuario de .NET MAUI.

  7. En la aplicación de .NET MAUI, actualice la clase App para que derive de la clase App en el proyecto de la interfaz de usuario de .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>
    

    A continuación, actualice el archivo de código subyacente de la clase App para que derive de la clase App en el proyecto de la interfaz de usuario de .NET MAUI y cargue los recursos de XAML desde este proyecto:

    public partial class TestApp : myMauiUIProject.App
    {
        public TestApp()
        {
            var baseResources = Resources;
            InitializeComponent();
            Resources.MergedDictionaries.Add(baseResources);
            MainPage = new HostPage();
        }
    }
    
  8. En la aplicación de .NET MAUI, agregue una página que muestre la interfaz de usuario del proyecto que contiene la interfaz de usuario de .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. En la aplicación de .NET MAUI, actualice la clase MauiProgram para llamar al método CreateMauiApp en el proyecto que contiene la interfaz de usuario de .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.
            });
    }
    

Ahora debería poder ejecutar el proyecto de la aplicación de .NET MAUI en cada plataforma y usar la Recarga activa de XAML para iterar en la interfaz de usuario de .NET MAUI.

Para obtener un ejemplo de este enfoque, consulte la aplicación de ejemplo.