Incorporation native
En règle générale, une application d’interface utilisateur d’application multiplateforme .NET (.NET MAUI) inclut des pages qui contiennent des dispositions, telles que Grid, et des dispositions qui contiennent des vues, telles que Button. Les pages, les mises en page et les vues dérivent de Element. L’incorporation native permet à tous les contrôles .NET MAUI qui dérivent de Element d’être utilisés dans les applications natives .NET pour Android, .NET pour iOS, .NET pour Mac Catalyst et WinUI.
Le processus de consommation d’un contrôle MAUI .NET dans une application native est le suivant :
- Créez des méthodes d’extension pour démarrer votre application incorporée native. Pour plus d’informations, consultez Créer des méthodes d’extension.
- Créez un projet unique .NET MAUI qui contient votre interface utilisateur .NET MAUI et toutes les dépendances. Pour plus d’informations, consultez Créer un projet .NET MAUI unique.
- Créez une application native et activez la prise en charge de .NET MAUI. Pour plus d’informations, consultez Activer la prise en charge de .NET MAUI.
- Initialisez .NET MAUI dans votre projet d’application natif. Pour plus d’informations, consultez Initialiser .NET MAUI.
- Créez l’interface utilisateur .NET MAUI et convertissez-la en type natif approprié avec la méthode d’extension
ToPlatformEmbedding
. Pour plus d’informations, consultez Consommer des contrôles .NET MAUI.
- Créez un projet unique .NET MAUI qui contient votre interface utilisateur .NET MAUI et toutes les dépendances. Pour plus d’informations, consultez Créer un projet .NET MAUI unique.
- Créez une application native et activez la prise en charge de .NET MAUI. Pour plus d’informations, consultez Activer la prise en charge de .NET MAUI.
- Initialisez .NET MAUI dans votre projet d’application natif. Pour plus d’informations, consultez Initialiser .NET MAUI.
- Créez l’interface utilisateur .NET MAUI et convertissez-la en type natif approprié avec la méthode d’extension
ToPlatformEmbedding
. Pour plus d’informations, consultez Consommer des contrôles .NET MAUI.
Remarque
Lorsque vous utilisez l’incorporation native, le moteur de liaison de données de .NET MAUI fonctionne toujours. Toutefois, la navigation de page doit être effectuée à l’aide de l’API de navigation native.
Créer des méthodes d’extension
Avant de créer une application native qui consomme des contrôles .NET MAUI, vous devez d’abord créer un projet de bibliothèque de classes .NET MAUI et supprimer le dossier Plateformes et la classe Class1
de celui-ci. Ensuite, ajoutez une classe à celle-ci nommée EmbeddedExtensions
qui contient le code suivant :
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>();
}
}
Ces méthodes d’extension se trouvent dans l’espace de noms Microsoft.Maui.Controls
et sont utilisées pour démarrer votre application incorporée native sur chaque plateforme. Les méthodes d’extension font référence les types EmbeddedPlatformApplication
, EmbeddedWindowHandler
et EmbeddedWindowProvider
que vous devez également ajouter au projet de bibliothèque .NET MAUI.
Le code suivant montre la classe EmbeddedPlatformApplication
, qui doit être ajoutée au même projet de bibliothèque .NET MAUI que la 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);
}
}
Le code suivant montre la classe EmbeddedWindowHandler
, qui doit être ajoutée au même projet de bibliothèque .NET MAUI que la 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.");
}
Le code suivant montre la classe EmbeddedWindowProvider
, qui doit être ajoutée au même projet de bibliothèque .NET MAUI que la 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;
}
Créer un projet .NET MAUI unique
Avant de créer une application native qui consomme des contrôles .NET MAUI, vous devez ajouter un projet d’application .NET MAUI à la même solution que le projet de bibliothèque de classes .NET MAUI que vous avez créé précédemment. Le projet d’application .NET MAUI stocke l’interface utilisateur que vous envisagez de réutiliser dans votre application incorporée native. Après avoir ajouté un nouveau projet d’application .NET MAUI à la solution, procédez comme suit :
Supprimez le dossier Propriétés du projet.
Supprimez le dossier Plateformes du projet.
Supprimez le dossier Resources/AppIcon du projet.
Supprimez le dossier Resources/raw du projet.
Supprimez le dossier Resources/Splash du projet.
Supprimez la classe
AppShell
du projet.Vérifiez que la
App
classe ne définit pas laMainPage
propriété ou ne remplace pas laCreateWindow
méthode :public partial class App : Application { public App() { InitializeComponent(); } }
Supprimez la classe
MainPage
du projet.Modifiez le fichier projet afin que la propriété de build
$(TargetFramework)
soit définie surnet8.0
, et la propriété de build$(OutputType)
est supprimée :<PropertyGroup> <TargetFramework>net8.0</TargetFramework> <RootNamespace>MyMauiApp</RootNamespace> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> ... </PropertyGroup>
Important
Vérifiez que vous définissez la propriété de build
$(TargetFramework)
, et non la propriété de build$(TargetFrameworks)
.Modifiez la méthode
CreateMauiApp
dans la classeMauiProgram
afin qu’elle accepte un argument facultatifAction<MauiAppBuilder>
appelé avant que la méthode ne retourne :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(); }
À ce stade, vous devez ajouter votre interface utilisateur .NET MAUI requise au projet, y compris toutes les dépendances et ressources, et vous assurer que le projet est généré correctement.
Créer un projet .NET MAUI unique
Avant de créer une application native qui consomme des contrôles .NET MAUI, vous devez ajouter un projet d’application .NET MAUI à la même solution que le projet de bibliothèque de classes .NET MAUI que vous avez créé précédemment. Le projet d’application .NET MAUI stocke l’interface utilisateur que vous envisagez de réutiliser dans votre application incorporée native. Après avoir ajouté un nouveau projet d’application .NET MAUI à la solution, procédez comme suit :
Supprimez le dossier Propriétés du projet.
Supprimez le dossier Plateformes du projet.
Supprimez le dossier Resources/AppIcon du projet.
Supprimez le dossier Resources/raw du projet.
Supprimez le dossier Resources/Splash du projet.
Supprimez la classe
AppShell
du projet.Vérifiez que la
App
classe ne définit pas laMainPage
propriété ou ne remplace pas laCreateWindow
méthode :public partial class App : Application { public App() { InitializeComponent(); } }
Supprimez la classe
MainPage
du projet.Modifiez le fichier projet afin que la propriété de build
$(TargetFramework)
soit définie surnet9.0
, et la propriété de build$(OutputType)
est supprimée :<PropertyGroup> <TargetFramework>net9.0</TargetFramework> <RootNamespace>MyMauiApp</RootNamespace> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> ... </PropertyGroup>
Important
Vérifiez que vous définissez la propriété de build
$(TargetFramework)
, et non la propriété de build$(TargetFrameworks)
.Dans la
MauiProgram
classe, modifiez laCreateMauiApp
méthode pour accepter unTApp
argument générique et acceptez un argument facultatifAction<MauiAppBuilder>
appelé avant que la méthode ne retourne. En outre, remplacez l’appel parUseMauiApp<App>
UseMauiEmbeddedApp<TApp>
:public static class MauiProgram { // Create a MauiApp using the specified application. public static MauiApp CreateMauiApp<TApp>(Action<MauiAppBuilder>? additional = null) where TApp : App { var builder = MauiApp.CreateBuilder(); builder .UseMauiEmbeddedApp<TApp>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); #if DEBUG builder.Logging.AddDebug(); #endif additional?.Invoke(builder); return builder.Build(); } }
Dans la
MauiProgram
classe, ajoutez uneCreateMauiApp
surcharge qui accepte un argument facultatifAction<MauiAppBuilder>
:public static class MauiProgram { ... // Create a MauiApp using the default application. public static MauiApp CreateMauiApp(Action<MauiAppBuilder>? additional = null) => CreateMauiApp<App>(additional); }
Vous devez ensuite ajouter votre interface utilisateur .NET MAUI requise au projet, y compris toutes les dépendances et ressources, et vous assurer que le projet est généré correctement.
Activer la prise en charge de .NET MAUI
Pour utiliser des contrôles .NET MAUI dérivés d’une application Element dans .NET pour Android, .NET pour iOS, .NET pour Mac Catalyst ou WinUI, vous devez ajouter votre projet d’application natif à la même solution que le projet de bibliothèque de classes .NET MAUI que vous avez créé précédemment. Ensuite, vous devez activer la prise en charge de .NET MAUI dans le fichier projet de votre application native en définissant les propriétés de build $(UseMaui)
et $(MauiEnablePlatformUsings)
sur true
dans le premier nœud <PropertyGroup>
du fichier projet :
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
</PropertyGroup>
Pour les applications .NET pour Mac Catalyst, vous devez également définir la propriété de build $(SupportedOSPlatformVersion)
sur un minimum de 14.0 :
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
</PropertyGroup>
Pour les applications .NET pour Mac Catalyst, vous devez également définir la $(SupportedOSPlatformVersion)
propriété de build sur un minimum de 15,0 :
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
</PropertyGroup>
Pour les applications WinUI, vous devez également définir la propriété de build $(EnableDefaultXamlItems)
sur false
:
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
<EnableDefaultXamlItems>false</EnableDefaultXamlItems>
</PropertyGroup>
Cela vous empêche de recevoir des erreurs de build sur la méthode InitializeComponent
déjà définie.
Ensuite, ajoutez des éléments de build $(PackageReference)
au fichier projet pour les packages NuGet Microsoft.Maui.Controls
et Microsoft.Maui.Controls.Compatiblity
:
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
</ItemGroup>
Ensuite, ajoutez $(PackageReference)
des éléments de build au fichier projet pour le Microsoft.Maui.Controls
package NuGet :
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
</ItemGroup>
Initialiser .NET MAUI
.NET MAUI doit être initialisé avant qu’un projet d’application native puisse construire un contrôle .NET MAUI. Le choix de l’initialisation dépend principalement du moment où il est le plus pratique dans votre flux d’application. Il peut être effectué au démarrage ou juste avant la construction d’un contrôle MAUI .NET. L’approche décrite ici consiste à initialiser .NET MAUI lorsque l’interface utilisateur initiale de l’application est créée.
En règle générale, le modèle d’initialisation de .NET MAUI dans un projet d’application native est le suivant :
- Créez un objet MauiApp.
- Créer un objet MauiContext de l'objet MauiApp. L’objet MauiContext sera utilisé pour obtenir une vue native à partir de la vue .NET MAUI.
Sur Android, le remplacement OnCreate
dans la classe est généralement l’endroit où effectuer des tâches liées au démarrage de l’application MainActivity
. L’exemple de code suivant montre que .NET MAUI est initialisé dans la 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
...
}
}
Sur iOS et Mac Catalyst, la classe AppDelegate
doit être modifiée pour retourner true
pour le remplacement 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;
}
La méthode WillConnect
de la classe SceneDelegate
doit ensuite être modifiée pour créer votre contrôleur de vue principal et la définir comme vue de l’élément 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();
}
...
}
Ensuite, dans l’éditeur XML, ouvrez le fichier Info.plist et ajoutez le code XML suivant à la fin du fichier :
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
.NET MAUI peut ensuite être initialisé dans la méthode ViewDidLoad
dans votre contrôleur de vue 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
...
}
}
Sur Windows, la classe MainWindow
est généralement l’endroit où effectuer des tâches de démarrage d’application associées à l’interface utilisateur :
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
...
}
}
Dans cet exemple, l’objet MauiApp est créé à l’aide d’une initialisation différée. La méthode d’extension UseMauiEmbedding
est appelée sur l’objet MauiAppBuilder. Par conséquent, votre projet d’application native doit inclure une référence au projet de bibliothèque de classes .NET MAUI que vous avez créé qui contient cette méthode d’extension. Un objet MauiContext est ensuite créé à partir de l’objet MauiApp , avec une détermination bool
à partir de laquelle le contexte est délimité. L’objet MauiContext sera utilisé lors de la conversion de contrôles .NET MAUI en types natifs.
L’incorporation peut être effectuée dans un contexte d’application ou un contexte de fenêtre, mais pour une compatibilité .NET MAUI maximale, elle doit être effectuée dans un contexte de fenêtre.
Contexte de l’application
L’incorporation native peut être effectuée dans un contexte d’application, où l’application native n’a aucune connaissance d’une fenêtre. Avec cette approche, l’initialisation d’incorporation native vous oblige à :
- Créez un objet MauiApp.
- Créer un objet MauiContext de l'objet MauiApp. L’objet MauiContext sera utilisé pour obtenir une vue native à partir de la vue .NET MAUI.
L’exemple suivant montre cette approche :
var mauiApp = MauiProgram.CreateMauiApp();
var context = new MauiContext(mauiApp.Services); // Activity also needs passing on Android
Une vue MAUI .NET peut ensuite être créée et convertie en vue native avec la ToPlatformEmbedded
méthode d’extension, ce qui nécessite l’objet MauiContext en tant qu’argument.
Cette approche convient aux scénarios où une application native doit incorporer une interface utilisateur .NET MAUI simple, mais n’a pas besoin d’accéder à toutes les fonctionnalités .NET MAUI. L’inconvénient de cette approche est que les outils tels que le rechargement à chaud et certaines fonctionnalités MAUI .NET ne fonctionnent pas.
Conseil
La création d’un MauiApp objet chaque fois qu’une vue MAUI .NET est incorporée en tant qu’affichage natif n’est pas recommandée. Cela peut être problématique si les vues incorporées accèdent à la Application.Current
propriété. Au lieu de cela, l’objet MauiApp peut être créé en tant qu’instance statique partagée :
public static class MyEmbeddedMauiApp
{
static MauiApp? _shared;
public static MauiApp Shared => _shared ??= MauiProgram.CreateMauiApp();
}
Avec cette approche, vous pouvez instancier l’objet MauiApp au début du cycle de vie de votre application pour éviter d’avoir un petit délai la première fois que vous incorporez une vue MAUI .NET dans votre application.
Sur Android, un fragment représente une partie de l’interface utilisateur au sein d’une activité. L’exemple de code suivant montre que .NET MAUI est initialisé dans un fragment :
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);
...
}
}
Sur iOS et Mac Catalyst, la classe AppDelegate
doit être modifiée pour retourner true
pour le remplacement 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;
}
La méthode WillConnect
de la classe SceneDelegate
doit ensuite être modifiée pour créer votre contrôleur de vue principal et la définir comme vue de l’élément 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();
}
...
}
Ensuite, dans l’éditeur XML, ouvrez le fichier Info.plist et ajoutez le code XML suivant à la fin du fichier :
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
.NET MAUI peut ensuite être initialisé dans la méthode ViewDidLoad
dans votre contrôleur de vue 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);
...
}
}
Sur Windows, la classe MainWindow
est généralement l’endroit où effectuer des tâches de démarrage d’application associées à l’interface utilisateur :
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);
...
}
}
Dans cet exemple, l’objet MauiApp est créé en tant qu’instance statique partagée. Lorsque cet objet est créé, MauiProgram.CreateMauiApp
est appelé à son tour la UseMauiEmbedding
méthode d’extension sur l’objet MauiAppBuilder . Par conséquent, votre projet d’application native doit inclure une référence au projet de bibliothèque de classes .NET MAUI que vous avez créé qui contient votre MauiProgram
classe et votre interface utilisateur MAUI .NET. Un MauiContext objet est ensuite créé à partir de l’objet MauiApp , qui est délimité à l’objet MauiApp . L’objet MauiContext sera utilisé lors de la conversion de contrôles .NET MAUI en types natifs.
Contexte de fenêtre
L’incorporation native peut être effectuée dans un contexte de fenêtre, où l’application native a connaissance d’une fenêtre. Dans certains scénarios, les vues MAUI .NET nécessitent l’accès à une fenêtre pour fonctionner correctement. Par exemple, les déclencheurs adaptatifs nécessitent l’accès à la fenêtre d’une vue et s’il n’y a pas de fenêtre qu’ils ne fonctionnent pas.
Avec cette approche, l’initialisation d’incorporation native vous oblige à :
- Créez un objet MauiApp.
- Créez un MauiContext objet avec la
CreateEmbeddedWindowContext
méthode. L’objet MauiContext sera utilisé pour obtenir une vue native à partir de la vue .NET MAUI.
La CreateEmbeddedWindowContext
méthode crée un contexte de fenêtre qui associe une fenêtre native à une fenêtre .NET MAUI :
var mauiApp = MauiProgram.CreateMauiApp();
var context = mauiApp.CreateEmbeddedWindowContext(this);
Une vue MAUI .NET peut ensuite être créée et convertie en vue native avec la ToPlatformEmbedded
méthode d’extension, ce qui nécessite l’objet MauiContext en tant qu’argument.
Remarque
La ToPlatformEmbedded
méthode d’extension a une surcharge qui ajoute une vue MAUI .NET à une fenêtre incorporée.
L’avantage de cette approche est qu’il existe une seule fenêtre MAUI .NET pour chaque fenêtre native, les API liées aux fenêtres fonctionnent correctement, et les outils tels que le rechargement à chaud fonctionnent correctement.
Conseil
La création d’un MauiApp objet chaque fois qu’une vue MAUI .NET est incorporée en tant qu’affichage natif n’est pas recommandée. Cela peut être problématique si les vues incorporées accèdent à la Application.Current
propriété. Au lieu de cela, l’objet MauiApp peut être créé en tant qu’instance statique partagée :
public static class MyEmbeddedMauiApp
{
static MauiApp? _shared;
public static MauiApp Shared => _shared ??= MauiProgram.CreateMauiApp();
}
Avec cette approche, vous pouvez instancier l’objet MauiApp au début du cycle de vie de votre application pour éviter d’avoir un petit délai la première fois que vous incorporez une vue MAUI .NET dans votre application.
Sur Android, un fragment représente une partie de l’interface utilisateur au sein d’une activité. L’exemple de code suivant montre que .NET MAUI est initialisé dans un fragment :
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;
...
}
}
Sur iOS et Mac Catalyst, la classe AppDelegate
doit être modifiée pour retourner true
pour le remplacement 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;
}
La méthode WillConnect
de la classe SceneDelegate
doit ensuite être modifiée pour créer votre contrôleur de vue principal et la définir comme vue de l’élément 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();
}
...
}
Ensuite, dans l’éditeur XML, ouvrez le fichier Info.plist et ajoutez le code XML suivant à la fin du fichier :
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
.NET MAUI peut ensuite être initialisé dans la méthode ViewDidLoad
dans votre contrôleur de vue 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;
...
}
}
Sur Windows, la classe MainWindow
est généralement l’endroit où effectuer des tâches de démarrage d’application associées à l’interface utilisateur :
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;
...
}
}
Dans cet exemple, l’objet MauiApp est créé en tant qu’instance statique partagée. Lorsque cet objet est créé, MauiProgram.CreateMauiApp
est appelé à son tour la UseMauiEmbedding
méthode d’extension sur l’objet MauiAppBuilder . Par conséquent, votre projet d’application native doit inclure une référence au projet de bibliothèque de classes .NET MAUI que vous avez créé qui contient votre MauiProgram
classe et votre interface utilisateur MAUI .NET. Un MauiContext objet est ensuite créé avec la CreateEmbeddedWindowContext
méthode, qui est délimité à la fenêtre. L’objet MauiContext sera utilisé lors de la conversion de contrôles .NET MAUI en types natifs.
Consommer des contrôles .NET MAUI
Une fois que .NET MAUI a été initialisé dans votre application native, vous pouvez ajouter votre interface utilisateur MAUI .NET à la disposition de votre application native. Pour ce faire, créez une instance de l’interface utilisateur et convertissez-la en type natif approprié avec la méthode d’extension ToPlatformEmbedded
.
Sur Android, la méthode d’extension ToPlatformEmbedded
convertit le contrôle .NET MAUI en objet View Android :
var mauiView = new MyMauiContent();
Android.Views.View nativeView = mauiView.ToPlatformEmbedded(context);
Dans cet exemple, un ContentViewobjet dérivé est converti en objet View Android.
Remarque
La méthode d’extension ToPlatformEmbedded
se trouve dans la bibliothèque de classes .NET MAUI que vous avez créée précédemment. Par conséquent, votre projet d’application native doit inclure une référence à ce projet.
Remarque
La ToPlatformEmbedded
méthode d’extension se trouve dans l’espace Microsoft.Maui.Controls.Embedding de noms. Par conséquent, votre projet d’application native doit inclure une using
instruction pour cet espace de noms.
L’objet View peut ensuite être ajouté à une disposition dans votre application native :
rootLayout.AddView(nativeView, new LinearLayout.LayoutParams(MatchParent, WrapContent));
Sur iOS et Mac Catalyst, la méthode d’extension ToPlatformEmbedded
convertit le contrôle .NET MAUI en objet UIView :
var mauiView = new MyMauiContent();
UIView nativeView = mauiView.ToPlatformEmbedded(context);
nativeView.WidthAnchor.ConstraintEqualTo(View.Frame.Width).Active = true;
nativeView.HeightAnchor.ConstraintEqualTo(500).Active = true;
Dans cet exemple, un objet dérivé de ContentView est converti en objet UIView, puis les contraintes de largeur et de hauteur sont définies sur cet objet pour permettre l’interaction.
Remarque
La méthode d’extension ToPlatformEmbedded
se trouve dans la bibliothèque de classes .NET MAUI que vous avez créée précédemment. Par conséquent, votre projet d’application native doit inclure une référence à ce projet.
L’objet UIView peut ensuite être ajouté à une vue dans votre contrôleur de vue :
stackView.AddArrangedSubView(nativeView);
var mauiView = new MyMauiContent();
UIView nativeView = mauiView.ToPlatformEmbedded(context);
Dans cet exemple, un objet dérivé ContentView est converti en objet UIView.
Remarque
La ToPlatformEmbedded
méthode d’extension se trouve dans l’espace Microsoft.Maui.Controls.Embedding de noms. Par conséquent, votre projet d’application native doit inclure une using
instruction pour cet espace de noms.
L’objet UIView peut ensuite être ajouté à une vue dans votre contrôleur de vue :
stackView.AddArrangedSubView(new ContainerView(nativeView));
ContainerView
est un type personnalisé qui encapsule la vue .NET MAUI pour vous assurer qu’elle est correctement dimensionnée. Pour ce faire, vous IntrinsicContentSize
êtes redirigé vers la vue SizeThatFits
.NET MAUI :
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();
}
}
En outre, une méthode d’extension ToUIViewController
dans .NET MAUI peut être utilisée pour convertir une page .NET MAUI en un UIViewController:
MyMauiPage myMauiPage = new MyMauiPage();
UIViewController myPageController = myMauiPage.ToUIViewController(context);
Dans cet exemple, un objet dérivé ContentPage est converti en un UIViewController.
Sur Windows, la méthode d’extension ToPlatformEmbedded
convertit le contrôle .NET MAUI en objet FrameworkElement :
var mauiView = new MyMauiContent();
FrameworkElement nativeView = myMauiPage.ToPlatformEmbedded(context);
Dans cet exemple, un objet dérivé ContentView est converti en objet FrameworkElement. L’objet FrameworkElement peut ensuite être défini comme contenu d’une page WinUI.
Remarque
La méthode d’extension ToPlatformEmbedded
se trouve dans la bibliothèque de classes .NET MAUI que vous avez créée précédemment. Par conséquent, votre projet d’application native doit inclure une référence à ce projet.
Remarque
La ToPlatformEmbedded
méthode d’extension se trouve dans l’espace Microsoft.Maui.Controls.Embedding de noms. Par conséquent, votre projet d’application native doit inclure une using
instruction pour cet espace de noms.
L’objet FrameworkElement peut ensuite être ajouté à une disposition dans votre application native :
stackPanel.Children.Add(nativeView);
Important
Pour éviter une erreur, le rechargement à chaud XAML doit être désactivé avant d’exécuter une application incorporée native dans la configuration de débogage.
Prise en charge du rechargement à chaud XAML
Le rechargement à chaud XAML n’est pas pris en charge dans les applications incorporées natives. Toutefois, vous pouvez toujours utiliser le rechargement à chaud XAML pour itérer rapidement sur votre interface utilisateur .NET MAUI en créant une application MAUI .NET qui consomme l’interface utilisateur .NET MAUI.
Pour afficher votre interface utilisateur .NET MAUI avec le rechargement à chaud XAML :
Dans le projet contenant votre interface utilisateur .NET MAUI, mettez à jour la classe
MauiProgram
pour ajouter une surcharge deCreateMauiApp
et modifiez la méthodeCreateMauiApp
existante pour qu’elle accepte un argument générique :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(); } }
Dans le projet contenant votre interface utilisateur .NET MAUI, convertissez chaque dictionnaire de ressources d’un fichier XAML autonome en dictionnaire de ressources s’appuyant sur un fichier code-behind.
Dans le projet contenant votre interface utilisateur .NET MAUI, mettez à jour l’instanciation de votre dictionnaire de ressources, généralement dans App.xaml, afin que la propriété
Source
spécifie également l’assembly qui contient le dictionnaire de ressources :<ResourceDictionary Source="Resources/Styles/Colors.xaml;assembly=NativeEmbeddingDemo" /> <ResourceDictionary Source="Resources/Styles/Styles.xaml;assembly=NativeEmbeddingDemo" />
Créez une application .NET MAUI et ajoutez-la à la solution contenant votre projet d’interface utilisateur .NET MAUI et vos applications incorporées natives.
Dans votre projet d’application .NET MAUI, ajoutez une référence au projet qui contient votre interface utilisateur .NET MAUI.
Dans votre projet d’application .NET MAUI, supprimez les dossiers enfants Ressource dans lesquels la ressource est fournie par votre projet d’interface utilisateur .NET MAUI. Par exemple, si votre projet d’interface utilisateur .NET MAUI contient des dossiers Resources > Polices, Resources > Images et Resources > Styles, ces dossiers doivent être supprimés de l’application .NET MAUI que vous venez de créer. Cela permet à votre application .NET MAUI d’utiliser les ressources du projet contenant votre interface utilisateur .NET MAUI.
Dans votre application .NET MAUI, mettez à jour votre classe
App
afin qu’elle dérive de la classeApp
dans votre projet d’interface utilisateur .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>
Ensuite, mettez à jour le fichier code-behind de la classe
App
afin qu’elle dérive de la classeApp
dans votre projet d’interface utilisateur .NET MAUI et charge les ressources XAML de ce projet :public partial class TestApp : myMauiUIProject.App { public TestApp() { var baseResources = Resources; InitializeComponent(); Resources.MergedDictionaries.Add(baseResources); MainPage = new HostPage(); } }
Dans votre application .NET MAUI, ajoutez une page qui affiche l’interface utilisateur du projet contenant votre interface utilisateur .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>
Dans votre application .NET MAUI, mettez à jour la classe
MauiProgram
pour qu’elle appelle la méthodeCreateMauiApp
dans le projet contenant votre interface utilisateur .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. }); }
Vous devriez maintenant être en mesure d’exécuter votre projet d’application .NET MAUI sur chaque plateforme et d’utiliser le rechargement à chaud XAML pour itérer sur votre interface utilisateur .NET MAUI.
Pour obtenir un exemple de cette approche, consultez l’exemple d’application.