ネイティブ埋め込み
通常、.NET Multi-platform App UI (.NET MAUI) アプリには、Grid などのレイアウトを含むページや、Button などのビューを含むレイアウトが含まれます。 ページ、レイアウト、ビューはすべて、Element から派生します。 ネイティブ埋め込みを使用すると、.NET for Android、.NET for iOS、.NET for Mac Catalyst、WinUI ネイティブ アプリで Element から派生するすべての .NET MAUI コントロールを使用できます。
ネイティブ アプリで .NET MAUI コントロールを使用するプロセスは次のとおりです。
- ネイティブ埋め込みアプリをブートストラップする拡張メソッドを作成します。 詳細については、「拡張メソッドの作成」を参照してください。
- .NET MAUI UI と依存関係を含む .NET MAUI 単一プロジェクトを作成します。 詳細については、「.NET MAUI 単一プロジェクトの作成」を参照してください。
- ネイティブ アプリを作成し、その中で .NET MAUI のサポートを有効にします。 詳細については、「.NET MAUI のサポート を有効にする」を参照してください。
UseMauiEmbedding
拡張メソッドを呼び出して .NET MAUI を初期化します。 詳細については、「.NET MAUI の初期化」を参照してください。- .NET MAUI UI を作成し、
ToPlatformEmbedding
拡張メソッドを使用して適切なネイティブ型に変換します。 詳細については、「.NET MAUI コントロール の使用」を参照してください。
Note
ネイティブ埋め込みを使用しても、.NET MAUI のデータ バインディング エンジンは引き続き機能します。 ただし、ページ ナビゲーションはネイティブ ナビゲーション API を使用して実行する必要があります。
拡張メソッドを作成する
.NET MAUI コントロールを使用するネイティブ アプリを作成する前に、まず .NET MAUI クラス ライブラリ プロジェクトを作成し、Platforms フォルダーとその Class1
クラスを削除する必要があります。 次に、次のコードを含む EmbeddedExtensions
という名前のクラスをそれに追加します:
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.Platform;
#if ANDROID
using PlatformView = Android.Views.View;
using PlatformWindow = Android.App.Activity;
using PlatformApplication = Android.App.Application;
#elif IOS || MACCATALYST
using PlatformView = UIKit.UIView;
using PlatformWindow = UIKit.UIWindow;
using PlatformApplication = UIKit.IUIApplicationDelegate;
#elif WINDOWS
using PlatformView = Microsoft.UI.Xaml.FrameworkElement;
using PlatformWindow = Microsoft.UI.Xaml.Window;
using PlatformApplication = Microsoft.UI.Xaml.Application;
#endif
namespace Microsoft.Maui.Controls;
public static class EmbeddedExtensions
{
public static MauiAppBuilder UseMauiEmbedding(this MauiAppBuilder builder, PlatformApplication? platformApplication = null)
{
#if ANDROID
platformApplication ??= (Android.App.Application)Android.App.Application.Context;
#elif IOS || MACCATALYST
platformApplication ??= UIKit.UIApplication.SharedApplication.Delegate;
#elif WINDOWS
platformApplication ??= Microsoft.UI.Xaml.Application.Current;
#endif
builder.Services.AddSingleton(platformApplication);
builder.Services.AddSingleton<EmbeddedPlatformApplication>();
builder.Services.AddScoped<EmbeddedWindowProvider>();
// Returning null is acceptable here as the platform window is optional - but we don't know until we resolve it
builder.Services.AddScoped<PlatformWindow>(svc => svc.GetRequiredService<EmbeddedWindowProvider>().PlatformWindow!);
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IMauiInitializeService, EmbeddedInitializeService>());
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler(typeof(Window), typeof(EmbeddedWindowHandler));
});
return builder;
}
public static IMauiContext CreateEmbeddedWindowContext(this MauiApp mauiApp, PlatformWindow platformWindow, Window? window = null)
{
var windowScope = mauiApp.Services.CreateScope();
#if ANDROID
var windowContext = new MauiContext(windowScope.ServiceProvider, platformWindow);
#else
var windowContext = new MauiContext(windowScope.ServiceProvider);
#endif
window ??= new Window();
var wndProvider = windowContext.Services.GetRequiredService<EmbeddedWindowProvider>();
wndProvider.SetWindow(platformWindow, window);
window.ToHandler(windowContext);
return windowContext;
}
public static PlatformView ToPlatformEmbedded(this IElement element, IMauiContext context)
{
var wndProvider = context.Services.GetService<EmbeddedWindowProvider>();
if (wndProvider is not null && wndProvider.Window is Window wnd && element is VisualElement visual)
wnd.AddLogicalChild(visual);
return element.ToPlatform(context);
}
private class EmbeddedInitializeService : IMauiInitializeService
{
public void Initialize(IServiceProvider services) =>
services.GetRequiredService<EmbeddedPlatformApplication>();
}
}
これらの拡張メソッドは Microsoft.Maui.Controls
名前空間内にあり、各プラットフォームでネイティブ埋め込みアプリをブートストラップするために使用されます。 拡張メソッドは、.NET MAUI ライブラリ プロジェクトにも追加する必要のある EmbeddedPlatformApplication
、EmbeddedWindowHandler
、EmbeddedWindowProvider
型を参照します。
次のコードは、EmbeddedPlatformApplication
クラスを示しています。このクラスは、EmbeddedExtensions
クラスと同じ .NET MAUI ライブラリ プロジェクトに追加する必要があります:
#if ANDROID
using PlatformApplication = Android.App.Application;
#elif IOS || MACCATALYST
using PlatformApplication = UIKit.IUIApplicationDelegate;
#elif WINDOWS
using PlatformApplication = Microsoft.UI.Xaml.Application;
#endif
namespace Microsoft.Maui.Controls;
internal class EmbeddedPlatformApplication : IPlatformApplication
{
private readonly MauiContext rootContext;
private readonly IMauiContext applicationContext;
public IServiceProvider Services { get; }
public IApplication Application { get; }
public EmbeddedPlatformApplication(IServiceProvider services)
{
IPlatformApplication.Current = this;
#if ANDROID
var platformApp = services.GetRequiredService<PlatformApplication>();
rootContext = new MauiContext(services, platformApp);
#else
rootContext = new MauiContext(services);
#endif
applicationContext = MakeApplicationScope(rootContext);
Services = applicationContext.Services;
Application = Services.GetRequiredService<IApplication>();
}
private static IMauiContext MakeApplicationScope(IMauiContext rootContext)
{
var scopedContext = new MauiContext(rootContext.Services);
InitializeScopedServices(scopedContext);
return scopedContext;
}
private static void InitializeScopedServices(IMauiContext scopedContext)
{
var scopedServices = scopedContext.Services.GetServices<IMauiInitializeScopedService>();
foreach (var service in scopedServices)
service.Initialize(scopedContext.Services);
}
}
次のコードは、EmbeddedWindowHandler
クラスを示しています。このクラスは、EmbeddedExtensions
クラスと同じ .NET MAUI ライブラリ プロジェクトに追加する必要があります:
using Microsoft.Maui.Handlers;
#if ANDROID
using PlatformWindow = Android.App.Activity;
#elif IOS || MACCATALYST
using PlatformWindow = UIKit.UIWindow;
#elif WINDOWS
using PlatformWindow = Microsoft.UI.Xaml.Window;
#endif
namespace Microsoft.Maui.Controls;
internal class EmbeddedWindowHandler : ElementHandler<IWindow, PlatformWindow>, IWindowHandler
{
public static IPropertyMapper<IWindow, IWindowHandler> Mapper =
new PropertyMapper<IWindow, IWindowHandler>(ElementHandler.ElementMapper)
{
};
public static CommandMapper<IWindow, IWindowHandler> CommandMapper =
new CommandMapper<IWindow, IWindowHandler>(ElementHandler.ElementCommandMapper)
{
};
public EmbeddedWindowHandler() : base(Mapper)
{
}
protected override PlatformWindow CreatePlatformElement() =>
MauiContext!.Services.GetRequiredService<PlatformWindow>() ??
throw new InvalidOperationException("EmbeddedWindowHandler could not locate a platform window.");
}
次のコードは、EmbeddedWindowProvider
クラスを示しています。このクラスは、EmbeddedExtensions
クラスと同じ .NET MAUI ライブラリ プロジェクトに追加する必要があります:
#if ANDROID
using PlatformWindow = Android.App.Activity;
#elif IOS || MACCATALYST
using PlatformWindow = UIKit.UIWindow;
#elif WINDOWS
using PlatformWindow = Microsoft.UI.Xaml.Window;
#endif
namespace Microsoft.Maui.Controls;
public class EmbeddedWindowProvider
{
WeakReference<PlatformWindow?>? platformWindow;
WeakReference<Window?>? window;
public PlatformWindow? PlatformWindow => Get(platformWindow);
public Window? Window => Get(window);
public void SetWindow(PlatformWindow? platformWindow, Window? window)
{
this.platformWindow = new WeakReference<PlatformWindow?>(platformWindow);
this.window = new WeakReference<Window?>(window);
}
private static T? Get<T>(WeakReference<T?>? weak) where T : class =>
weak is not null && weak.TryGetTarget(out var target) ? target : null;
}
.NET MAUI 単一プロジェクトの作成
.NET MAUI コントロールを使用するネイティブ アプリを作成する前に、以前に作成した .NET MAUI クラス ライブラリ プロジェクトと同じソリューションに .NET MAUI アプリ プロジェクトを追加する必要があります。 .NET MAUI アプリ プロジェクトには、ネイティブ埋め込みアプリで再利用する予定の UI が格納されます。 ソリューションに新しい .NET MAUI アプリ プロジェクトを追加した後、次の手順を実行します:
プロジェクトから [プロパティ] フォルダーを削除します。
Platforms フォルダーをプロジェクトから削除します。
プロジェクトから Resources/AppIcon フォルダーを削除します。
プロジェクトから Resources/raw フォルダーを削除します。
プロジェクトから Resources/Splash フォルダーを削除します。
プロジェクトから
AppShell
クラスを削除します。App
クラスを変更して、それでMainPage
プロパティが設定されないようにします:public partial class App : Application { public App() { InitializeComponent(); } }
プロジェクトから
MainPage
クラスを削除します。プロジェクト ファイルを変更して、
$(TargetFrameworks)
ビルド プロパティがnet8.0
に設定され、$(OutputType)
ビルド プロパティが削除されるようにします:<PropertyGroup> <TargetFrameworks>net8.0</TargetFrameworks> <RootNamespace>MyMauiApp</RootNamespace> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> ... </PropertyGroup>
CreateMauiApp
メソッドが戻る前に呼び出される省略可能なAction<MauiAppBuilder>
引数を受け入れるように、MauiProgram
クラス内のメソッドを変更します:public static MauiApp CreateMauiApp(Action<MauiAppBuilder>? additional = null) { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); #if DEBUG builder.Logging.AddDebug(); #endif additional?.Invoke(builder); return builder.Build(); }
この時点で、必要な .NET MAUI UI (依存関係やリソースを含む) をプロジェクトに追加し、プロジェクトが正しくビルドされていることを確認する必要があります。
.NET MAUI のサポートを有効にする
.NET for Android、.NET for iOS、.NET for Mac Catalyst、または WinUI アプリの Element から派生する .NET MAUI コントロールを使用するには、前に作成した .NET MAUI クラス ライブラリ プロジェクトと同じソリューションにネイティブ アプリ プロジェクトを追加する必要があります。 次に、プロジェクト ファイルの最初の <PropertyGroup>
ノードで $(UseMaui)
ビルド プロパティと $(MauiEnablePlatformUsings)
ビルド プロパティを true
に設定して、ネイティブ アプリのプロジェクト ファイルで .NET MAUI のサポートを有効にする必要があります:
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
</PropertyGroup>
.NET for Mac Catalyst アプリの場合は、$(SupportedOSPlatformVersion)
ビルド プロパティを 14.0 以上に設定する必要もあります。
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
</PropertyGroup>
WinUI アプリの場合は、$(EnableDefaultXamlItems)
ビルド プロパティを false
に設定する必要もあります:
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
<MauiEnablePlatformUsings>true</MauiEnablePlatformUsings>
<EnableDefaultXamlItems>false</EnableDefaultXamlItems>
</PropertyGroup>
これにより、既に定義されている InitializeComponent
メソッドに関するビルド エラーが受信されなくなります。
次に、$(PackageReference)
ビルド項目を Microsoft.Maui.Controls
NuGet パッケージと Microsoft.Maui.Controls.Compatiblity
NuGet パッケージのプロジェクト ファイルに追加します:
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
</ItemGroup>
.NET MAUI を初期化する
ネイティブ アプリ プロジェクトで .NET MAUI コントロールを構築する前に、.NET MAUI を初期化する必要があります。 それを初期化するタイミングの選択は、主にアプリ フローで最も便利なタイミングによって異なります。これは起動時または .NET MAUI コントロールが構築される直前に実行できます。 ここで説明する方法は、アプリの初期 UI が作成されたときに .NET MAUI を初期化することです。
通常、ネイティブ アプリ プロジェクトで .NET MAUI を初期化するパターンは次のとおりです:
- MauiApp オブジェクトを作成します。
- MauiApp オブジェクトから MauiContext オブジェクトを作成します。
Android では通常、MainActivity
クラスの OnCreate
オーバーライドが、アプリの起動に関連するタスクを実行する場所となります。 次のコード例は、MainActivity
クラスで初期化される .NET MAUI を示します。
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 mauiContext = UseWindowContext
? mauiApp.CreateEmbeddedWindowContext(this) // Create window context
: new MauiContext(mauiApp.Services, this); // Create app context
...
}
}
}
iOS および Mac Catalyst では、AppDelegate
クラスの FinishedLaunching
オーバーライドを変更してメイン ビュー コントローラーを作成する必要があります:
namespace MyNativeEmbeddedApp.iOS
{
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
public override UIWindow? Window { get; set; }
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var vc = new MainViewController();
Window.RootViewController = vc;
Window.MakeKeyAndVisible();
return true;
}
}
}
.NET MAUI は、メイン ビュー コントローラーの ViewDidLoad
メソッドで初期化できます:
using Microsoft.Maui.Platform;
namespace MyNativeEmbeddedApp.iOS
{
public class MainViewController : UIViewController
{
UIWindow GetWindow() =>
View?.Window ??
ParentViewController?.View?.Window ??
MainViewController.MauiApp.Value.Services.GetRequiredService<IUIApplicationDelegate>().GetWindow() ??
UIApplication.SharedApplication.Delegate.GetWindow();
public static readonly Lazy<MauiApp> MauiApp = new(() =>
{
var mauiApp = MauiProgram.CreateMauiApp(builder =>
{
builder.UseMauiEmbedding();
});
return mauiApp;
});
public static bool UseWindowContext = true;
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Ensure app is built before creating .NET MAUI views
var mauiApp = MainViewController.MauiApp.Value;
// Create .NET MAUI context
var mauiContext = UseWindowContext
? mauiApp.CreateEmbeddedWindowContext(GetWindow()) // Create window context
: new MauiContext(mauiApp.Services); // Create app context
...
}
}
}
Windows では、MainWindow
クラスは通常、UI 関連のアプリのスタートアップ タスクを実行する場所です:
namespace MyNativeEmbeddedApp.WinUI
{
public sealed partial class MainWindow : Microsoft.UI.Xaml.Window
{
public static readonly Lazy<MauiApp> MauiApp = new(() =>
{
var mauiApp = MauiProgram.CreateMauiApp(builder =>
{
builder.UseMauiEmbedding();
});
return mauiApp;
});
public static bool UseWindowContext = true;
public MainWindow()
{
this.InitializeComponent();
// Ensure .NET MAUI app is built before creating .NET MAUI views
var mauiApp = MainWindow.MauiApp.Value;
// Create .NET MAUI context
var mauiContext = UseWindowContext
? mauiApp.CreateEmbeddedWindowContext(this) // Create window context
: new MauiContext(mauiApp.Services); // Create app context
...
}
}
}
この例では、MauiApp オブジェクトは遅延初期化を使用して作成されます。 UseMauiEmbedding
拡張メソッドが MauiAppBuilder オブジェクトで呼び出されます。 そのため、ネイティブ アプリ プロジェクトには、この拡張メソッドを含む作成した .NET MAUI クラス ライブラリ プロジェクトへの参照を含める必要があります。 その後、MauiContext オブジェクトから MauiApp オブジェクトが生成され、bool
がコンテキストのスコープ元を決定します。 MauiContext オブジェクトは、.NET MAUI コントロールをネイティブ型に変換するときに使用します。
.NET MAUI コントロールを使用する
ネイティブ アプリで .NET MAUI が初期化されたら、ネイティブ アプリのレイアウトに .NET MAUI UI を追加できます。 これは、UI のインスタンスを作成し、ToPlatformEmbedded
拡張メソッドを使用して適切なネイティブ型に変換することで実現できます。
Android では、ToPlatformEmbedded
拡張メソッドは .NET MAUI コントロールを Android View オブジェクトに変換します:
var mauiView = new MyMauiContent();
Android.Views.View nativeView = mauiView.ToPlatformEmbedded(mauiContext);
この例では、ContentView から派生したオブジェクトが Android View オブジェクトに変換されます。
Note
ToPlatformEmbedded
拡張メソッドは、前に作成した .NET MAUI クラス ライブラリにあります。 そのため、ネイティブ アプリ プロジェクトには、そのプロジェクトへの参照を含める必要があります。
その後、View オブジェクトをネイティブ アプリのレイアウトに追加できます:
rootLayout.AddView(nativeView, new LinearLayout.LayoutParams(MatchParent, WrapContent));
iOS および Mac Catalyst では、ToPlatformEmbedded
拡張メソッドは .NET MAUI コントロールを UIView オブジェクトに変換します:
var mauiView = new MyMauiContent();
UIView nativeView = mauiView.ToPlatformEmbedded(mauiContext);
nativeView.WidthAnchor.ConstraintEqualTo(View.Frame.Width).Active = true;
nativeView.HeightAnchor.ConstraintEqualTo(500).Active = true;
この例では、ContentView 派生オブジェクトが UIView オブジェクトに変換されてから、やりとりを可能にするためにそのオブジェクトに幅と高さの制約が設定されます。
Note
ToPlatformEmbedded
拡張メソッドは、前に作成した .NET MAUI クラス ライブラリにあります。 そのため、ネイティブ アプリ プロジェクトには、そのプロジェクトへの参照を含める必要があります。
その後、UIView オブジェクトをビュー コントローラーのビューに追加できます:
stackView.AddArrangedSubView(nativeView);
さらに、.NET MAUI の ToUIViewController
拡張メソッドを使用して、.NET MAUI ページをUIViewController に変換できます:
MyMauiPage myMauiPage = new MyMauiPage();
UIViewController myPageController = myMauiPage.ToUIViewController(mauiContext);
この例では、ContentPage から派生したオブジェクトを UIViewController に変換しています。
Windows では、ToPlatformEmbedded
拡張メソッドは .NET MAUI コントロールを FrameworkElement
オブジェクトに変換します:
var mauiView = new MyMauiContent();
FrameworkElement nativeView = myMauiPage.ToPlatformEmbedded(mauiContext);
この例では、ContentView から派生したオブジェクトが FrameworkElement
オブジェクトに変換されます。 その後、FrameworkElement
オブジェクトを WinUI ページのコンテンツとして設定できます。
その後、FrameworkElement
オブジェクトをネイティブ アプリのレイアウトに追加できます:
stackPanel.Children.Add(nativeView);
重要
エラーが発生しないようにするには、デバッグ構成でネイティブ埋め込みアプリを実行する前に、XAML ホット リロードを無効にする必要があります。
.NET MAUI
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示