title | description | ms.date |
---|---|---|
Native embedding |
Learn how to consume .NET MAUI controls inside .NET iOS, .NET Android, and WinUI native apps. |
02/13/2022 |
Typically, a .NET Multi-platform App UI (.NET MAUI) app includes pages that contain layouts, such as xref:Microsoft.Maui.Controls.Grid, and layouts that contain views, such as xref:Microsoft.Maui.Controls.Button. Pages, layouts, and views all derive from xref:Microsoft.Maui.Controls.Element. Native embedding enables any .NET MAUI controls that derive from xref:Microsoft.Maui.Controls.Element to be consumed in .NET Android, .NET iOS, .NET for Mac Catalyst, and WinUI native apps.
The process for consuming a .NET MAUI control in a native app is as follows:
- Enable .NET MAUI support by adding
<UseMaui>true</UseMaui>
to the native app's project file. - Initialize .NET MAUI by calling the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method.
- Add your .NET MAUI code, such as code for a page, and any dependencies to the native project.
- Create an instance of the .NET MAUI control and convert it to the appropriate native type with the
ToPlatform
extension method.
Note
When using native embedding, .NET MAUI's data binding engine still works. However, page navigation must be performed using the native navigation API.
To consume .NET MAUI controls that derive from xref:Microsoft.Maui.Controls.Element in a .NET Android, .NET iOS, .NET for Mac Catalyst, or WinUI app, you must first enable .NET MAUI support in the native app's project file. Enable support by adding <UseMaui>true</UseMaui>
to the first <PropertyGroup>
node in the project file:
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
</PropertyGroup>
A consequence of doing this is that it replaces the native implicit namespace support with .NET MAUI namespaces, so you'll have to explicitly add using
statements to your code files for native types.
For WinUI apps, you'll also need to add <EnableDefaultXamlItems>false</EnableDefaultXamlItems>
to the first <PropertyGroup>
node in the project file:
<PropertyGroup>
...
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<UseMaui>true</UseMaui>
<EnableDefaultXamlItems>false</EnableDefaultXamlItems>
</PropertyGroup>
This will stop you receiving build errors about the InitializeComponent
method already being defined.
.NET MAUI must be initialized before a native app project can construct a .NET MAUI control. Choosing when to initialize it primarily depends on when it's most convenient in your app flow—it could be performed at startup or just before a .NET MAUI control is constructed.
Typically, the pattern for initializing .NET MAUI in a native app project is to create a xref:Microsoft.Maui.Hosting.MauiAppBuilder object, invoke the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method on it, and then create a xref:Microsoft.Maui.Hosting.MauiApp object by invoking the xref:Microsoft.Maui.Hosting.MauiAppBuilder.Build method on the xref:Microsoft.Maui.Hosting.MauiAppBuilder object. In addition, a xref:Microsoft.Maui.MauiContext object should then be created from the xref:Microsoft.Maui.Hosting.MauiApp object. The xref:Microsoft.Maui.MauiContext object will be used when converting .NET MAUI controls to native types.
The examples in the following sections show the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method being invoked at app startup.
On Android, the OnCreate
override in the MainActivity
class is typically the place to perform app startup related tasks. The following code example shows .NET MAUI being initialized in the MainActivity
class:
using Android.App;
using Android.OS;
using Android.Views;
using AndroidX.AppCompat.App;
using Microsoft.Maui.Embedding;
namespace Notes.Android;
public class MainActivity : AppCompatActivity
{
MauiContext _mauiContext;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Perform your normal Android registration
MauiAppBuilder builder = MauiApp.CreateBuilder();
builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>();
MauiApp mauiApp = builder.Build();
_mauiContext = new MauiContext(mauiApp.Services, this);
...
}
}
Note
The call to the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method can specify your own xref:Microsoft.Maui.Controls.Application derived class, such as MyApp
. For example, builder.UseMauiEmbedding<MyApp>();
.
On iOS and Mac Catalyst, the FinishedLaunching
override in the AppDelegate
class is typically the place to perform app startup related tasks. It's called after the app has launched, and is usually overridden to configure the main window and view controller. The following code example shows .NET MAUI being initialized in the AppDelegate
class:
using Foundation;
using Microsoft.Maui.Embedding;
using UIKit;
namespace Notes.MaciOS;
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
MauiContext _mauiContext;
public override UIWindow? Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// Perform your normal iOS registration
MauiAppBuilder builder = MauiApp.CreateBuilder();
builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>();
// Register the Window
builder.Services.Add(new Microsoft.Extensions.DependencyInjection.ServiceDescriptor(typeof(UIWindow), Window));
MauiApp mauiApp = builder.Build();
_mauiContext = new MauiContext(mauiApp.Services);
...
return true;
}
}
Note
The call to the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method can specify your own xref:Microsoft.Maui.Controls.Application derived class, such as MyApp
. For example, builder.UseMauiEmbedding<MyApp>();
.
On Windows apps built using WinUI, .NET MAUI can typically be initialized in the native App
class, Window
class, or a xref:Microsoft.Maui.Controls.Page class. The following code example shows .NET MAUI being initialized in a xref:Microsoft.Maui.Controls.Page class:
using Microsoft.Maui;
using Microsoft.Maui.Embedding;
using Microsoft.Maui.Hosting;
using Microsoft.UI.Xaml.Controls;
namespace Notes.Windows;
public sealed partial class MainPage : Page
{
public MauiContext _mauiContext;
public MainPage()
{
MauiAppBuilder builder = MauiApp.CreateBuilder();
builder.UseMauiEmbedding<Microsoft.Maui.Controls.Application>();
MauiApp mauiApp = builder.Build();
_mauiContext = new MauiContext(mauiApp.Services);
...
}
}
Note
The call to the xref:Microsoft.Maui.Embedding.AppHostBuilderExtensions.UseMauiEmbedding%2A method can specify your own xref:Microsoft.Maui.Controls.Application derived class, such as MyApp
. For example, builder.UseMauiEmbedding<MyApp>();
.
To consume .NET MAUI types that derive from xref:Microsoft.Maui.Controls.Element in native apps, create an instance of the control and convert it to the appropriate native type with the ToPlatform
extension method.
On Android, ToPlatform
converts the .NET MAUI control to an Android xref:Android.Views.View object:
MyMauiPage myMauiPage = new MyMauiPage();
Android.Views.View view = myMauiPage.ToPlatform(_mauiContext);
In this example, a xref:Microsoft.Maui.Controls.ContentPage-derived object is converted to an Android xref:Android.Views.View object.
Alternatively, a xref:Microsoft.Maui.Controls.ContentPage-derived object can be converted to a Fragment
with the following CreateSupportFragment
extension method:
using Android.OS;
using Android.Views;
using Microsoft.Maui.Platform;
using Fragment = AndroidX.Fragment.App.Fragment;
namespace Notes.Android;
public static class PageExtensions
{
public static Fragment CreateSupportFragment(this ContentPage view, MauiContext context)
{
return new ScopedFragment(view, context);
}
internal class ScopedFragment : Fragment
{
readonly IMauiContext _mauiContext;
public IView DetailView { get; private set; }
public ScopedFragment(IView detailView, IMauiContext mauiContext)
{
DetailView = detailView;
_mauiContext = mauiContext;
}
public override global::Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return DetailView.ToPlatform(_mauiContext);
}
}
}
The CreateSupportFragment
extension method can be consumed by invoking it on a xref:Microsoft.Maui.Controls.ContentPage-derived object:
MyMauiPage myMauiPage = new MyMauiPage();
AndroidX.Fragment.App.Fragment notesPageFragment = myMauiPage.CreateSupportFragment(_mauiContext);
The resulting Fragment
can then be managed by Android's FragmentManager
class.
For more information about Fragments, see Fragments on developer.android.com.
On iOS and Mac Catalyst, ToPlatform
converts the .NET MAUI control to a xref:UIKit.UIView object:
Button myButton = new Button { Text = ".NET MAUI" };
UIView button = myButton.ToPlatform(_mauiContext);
In this example, a xref:Microsoft.Maui.Controls.Button is converted to a xref:UIKit.UIView object.
In addition, a ToUIViewController
extension method can be used to attempt to convert a .NET MAUI control to a xref:UIKit.UIViewController:
MyMauiPage myMauiPage = new MyMauiPage();
UIViewController myPageController = myMauiPage.ToUIViewController(_mauiContext);
In this example, a xref:Microsoft.Maui.Controls.ContentPage-derived object is converted to a xref:UIKit.UIViewController.
On Windows, ToPlatform
converts the .NET MAUI control to a FrameworkElement
object:
MyMauiPage myMauiPage = new MyMauiPage();
FrameworkElement element = myMauiPage.ToPlatform(_mauiContext);
In this example, a xref:Microsoft.Maui.Controls.ContentPage-derived object is converted to a FrameworkElement
object. The FrameworkElement
object can then be set as the content of a WinUI page.