Manually upgrade a Xamarin.Forms app to a multi-project .NET MAUI app
Upgrading a multi-project Xamarin.Forms app to a multi-project .NET Multi-platform App UI (.NET MAUI) app follows the same steps as a Xamarin.Android and Xamarin.iOS project, with additional steps to take advantage of changes in .NET MAUI.
This article describes how to manually migrate a Xamarin.Forms library project to a .NET MAUI library project. Before you do this, you must update your Xamarin.Forms platform projects to be SDK-style projects. SDK-style projects are the same project format used by all .NET workloads, and compared to many Xamarin projects are much less verbose. For information about updating your app projects, see Upgrade Xamarin.Android, Xamarin.iOS, and Xamarin.Mac projects to .NET, Xamarin.Android project migration, Xamarin Apple project migration, and Xamarin.Forms UWP project migration.
To migrate a Xamarin.Forms library project to a .NET MAUI library project, you must:
- Update your Xamarin.Forms app to use Xamarin.Forms 5.
- Update the app's dependencies to the latest versions.
- Ensure the app still works.
- Update your project file to be SDK-style.
- Update namespaces.
- Address any API changes.
- Configure .NET MAUI.
- Upgrade or replace incompatible dependencies with .NET 8 versions.
- Compile and test your app.
To simplify the upgrade process, you should create a new .NET MAUI library project of the same name as your Xamarin.Forms library project, and then copy in your code, configuration, and resources. This is the approach outlined below.
Update your Xamarin.Forms app
Before upgrading your Xamarin.Forms app to .NET MAUI, you should first update your Xamarin.Forms app to use Xamarin.Forms 5 and ensure that it still runs correctly. In addition, you should update the dependencies that your app uses to the latest versions.
This will help to simplify the rest of the migration process, as it will minimize the API differences between Xamarin.Forms and .NET MAUI, and will ensure that you are using .NET compatible versions of your dependencies if they exist.
Create a new project
In Visual Studio, create a new .NET MAUI class library project of the same name as your Xamarin.Forms library project. This project will host the code from your Xamarin.Forms library project. Opening the project file will confirm that you have a .NET SDK-style project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>
</Project>
In your platform projects, add a reference to this new library project. Then copy your Xamarin.Forms library files into the .NET MAUI library project.
Namespace changes
Namespaces have changed in the move from Xamarin.Forms to .NET MAUI, and Xamarin.Essentials features are now part of .NET MAUI. To make namespace updates, perform a find and replace for the following namespaces:
.NET MAUI projects make use of implicit global using
directives. This feature enables you to remove using
directives for the Xamarin.Essentials
namespace, without having to replace them with the equivalent .NET MAUI namespaces.
In addition, the default XAML namespace has changed from http://xamarin.com/schemas/2014/forms
in Xamarin.Forms to http://schemas.microsoft.com/dotnet/2021/maui
in .NET MAUI. Therefore, you should replace all occurrences of xmlns="http://xamarin.com/schemas/2014/forms"
with xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
.
Note
You can quickly update your Xamarin.Forms
namespaces to Microsoft.Maui
by using Quick actions in Visual Studio, provided that you have Upgrade Assistant installed.
API changes
Some APIs have changed in the move from Xamarin.Forms to .NET MAUI. This is multiple reasons including removing duplicate functionality caused by Xamarin.Essentials becoming part of .NET MAUI, and ensuring that APIs follow .NET naming guidelines. The following sections discuss these changes.
Color changes
In Xamarin.Forms, the Xamarin.Forms.Color
struct lets you construct Color objects using double
values, and provides named colors, such as Xamarin.Forms.Color.AliceBlue
. In .NET MAUI, this functionality has been separated into the Microsoft.Maui.Graphics.Color class, and the Microsoft.Maui.Graphics.Colors class.
The Microsoft.Maui.Graphics.Color class, in the Microsoft.Maui.Graphics namespace, lets you construct Color objects using float
values, byte
values, and int
values. The Microsoft.Maui.Graphics.Colors class, which is also in the Microsoft.Maui.Graphics namespace, largely provides the same named colors. For example, use Colors.AliceBlue to specify the AliceBlue
color.
The following table shows the API changes between the Xamarin.Forms.Color
struct and the Microsoft.Maui.Graphics.Color class:
Xamarin.Forms API | .NET MAUI API | Comment |
---|---|---|
Xamarin.Forms.Color.R |
Microsoft.Maui.Graphics.Color.Red | |
Xamarin.Forms.Color.G |
Microsoft.Maui.Graphics.Color.Green | |
Xamarin.Forms.Color.B |
Microsoft.Maui.Graphics.Color.Blue | |
Xamarin.Forms.Color.A |
Microsoft.Maui.Graphics.Color.Alpha | |
Xamarin.Forms.Color.Hue |
Microsoft.Maui.Graphics.Color.GetHue | Xamarin.Forms property replaced with a method in .NET MAUI. |
Xamarin.Forms.Color.Saturation |
Microsoft.Maui.Graphics.Color.GetSaturation | Xamarin.Forms property replaced with a method in .NET MAUI. |
Xamarin.Forms.Color.Luminosity |
Microsoft.Maui.Graphics.Color.GetLuminosity | Xamarin.Forms property replaced with a method in .NET MAUI. |
Xamarin.Forms.Color.Default |
No .NET MAUI equivalent. Instead, Microsoft.Maui.Graphics.Color objects default to null . |
|
Xamarin.Forms.Color.Accent |
No .NET MAUI equivalent. | |
Xamarin.Forms.Color.FromHex |
Microsoft.Maui.Graphics.Color.FromArgb | Microsoft.Maui.Graphics.Color.FromHex is obsolete and will be removed in a future release. |
In addition, all of the numeric values in a Microsoft.Maui.Graphics.Color are float
, rather than double
as used in Xamarin.Forms.Color
.
Note
Unlike Xamarin.Forms, a Microsoft.Maui.Graphics.Color doesn't have an implicit conversion to System.Drawing.Color.
Layout changes
The following table lists the layout APIs that have been removed in the move from Xamarin.Forms to .NET MAUI:
Xamarin.Forms API | .NET MAUI API | Comments |
---|---|---|
Xamarin.Forms.AbsoluteLayout.IAbsoluteList<T>.Add |
The Add overload that accepts 3 arguments isn't present in .NET MAUI. |
|
Xamarin.Forms.Grid.IGridList<T>.AddHorizontal |
No .NET MAUI equivalent. | |
Xamarin.Forms.Grid.IGridList<T>.AddVertical |
No .NET MAUI equivalent. | |
Xamarin.Forms.RelativeLayout |
Microsoft.Maui.Controls.Compatibility.RelativeLayout | In .NET MAUI, RelativeLayout only exists as a compatibility control for users migrating from Xamarin.Forms. Use Grid instead, or add the xmlns for the compatibility namespace. |
In addition, adding children to a layout in code in Xamarin.Forms is accomplished by adding the children to the layout's Children
collection:
Grid grid = new Grid();
grid.Children.Add(new Label { Text = "Hello world" });
In .NET MAUI, the Children collection is for internal use by .NET MAUI and shouldn't be manipulated directly. Therefore, in code children should be added directly to the layout:
Grid grid = new Grid();
grid.Add(new Label { Text = "Hello world" });
Important
Any Add
layout extension methods, such as GridExtensions.Add, are invoked on the layout rather than the layouts Children collection.
You may notice when running your upgraded .NET MAUI app that layout behavior is different. For more information, see Layout behavior changes from Xamarin.Forms.
Custom layout changes
The process for creating a custom layout in Xamarin.Forms involves creating a class that derives from Layout<View>
, and overriding the VisualElement.OnMeasure
and Layout.LayoutChildren
methods. For more information, see Create a custom layout in Xamarin.Forms.
In .NET MAUI, the layout classes derive from the abstract Layout class. This class delegates cross-platform layout and measurement to a layout manager class. Each layout manager class implements the ILayoutManager interface, which specifies that Measure and ArrangeChildren implementations must be provided:
- The Measure implementation calls IView.Measure on each view in the layout, and returns the total size of the layout given the constraints.
- The ArrangeChildren implementation determines where each view should be placed within the bounds of the layout, and calls Arrange on each view with its appropriate bounds. The return value is the actual size of the layout.
For more information, see Custom layouts.
Device changes
Xamarin.Forms has a Xamarin.Forms.Device
class that helps you to interact with the device and platform the app is running on. The equivalent class in .NET MAUI, Microsoft.Maui.Controls.Device, is deprecated and its functionality is replaced by multiple types.
The following table shows the .NET MAUI replacements for the functionality in the Xamarin.Forms.Device
class:
Xamarin.Forms API | .NET MAUI API | Comments |
---|---|---|
Xamarin.Forms.Device.Android |
Microsoft.Maui.Devices.DevicePlatform.Android | |
Xamarin.Forms.Device.iOS |
Microsoft.Maui.Devices.DevicePlatform.iOS | |
Xamarin.Forms.Device.GTK |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.macOS |
No .NET MAUI equivalent. Instead, use Microsoft.Maui.Devices.DevicePlatform.MacCatalyst. | |
Xamarin.Forms.Device.Tizen |
Microsoft.Maui.Devices.DevicePlatform.Tizen | |
Xamarin.Forms.Device.UWP |
Microsoft.Maui.Devices.DevicePlatform.WinUI | |
Xamarin.Forms.Device.WPF |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.Flags |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.FlowDirection |
Microsoft.Maui.ApplicationModel.AppInfo.RequestedLayoutDirection | |
Xamarin.Forms.Device.Idiom |
Microsoft.Maui.Devices.DeviceInfo.Idiom | |
Xamarin.Forms.Device.IsInvokeRequired |
Microsoft.Maui.Dispatching.Dispatcher.IsDispatchRequired | |
Xamarin.Forms.Device.OS |
Microsoft.Maui.Devices.DeviceInfo.Platform | |
Xamarin.Forms.Device.RuntimePlatform |
Microsoft.Maui.Devices.DeviceInfo.Platform | |
Xamarin.Forms.Device.BeginInvokeOnMainThread |
Microsoft.Maui.ApplicationModel.MainThread.BeginInvokeOnMainThread | |
Xamarin.Forms.Device.GetMainThreadSynchronizationContextAsync |
Microsoft.Maui.ApplicationModel.MainThread.GetMainThreadSynchronizationContextAsync | |
Xamarin.Forms.Device.GetNamedColor |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.GetNamedSize |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.Invalidate |
Microsoft.Maui.Controls.VisualElement.InvalidateMeasure | |
Xamarin.Forms.Device.InvokeOnMainThreadAsync |
Microsoft.Maui.ApplicationModel.MainThread.InvokeOnMainThreadAsync | |
Xamarin.Forms.Device.OnPlatform |
Microsoft.Maui.Devices.DeviceInfo.Platform | |
Xamarin.Forms.Device.OpenUri |
Microsoft.Maui.ApplicationModel.Launcher.OpenAsync | |
Xamarin.Forms.Device.SetFlags |
No .NET MAUI equivalent. | |
Xamarin.Forms.Device.SetFlowDirection |
Microsoft.Maui.Controls.Window.FlowDirection | |
Xamarin.Forms.Device.StartTimer |
Microsoft.Maui.Dispatching.DispatcherExtensions.StartTimer or Microsoft.Maui.Dispatching.Dispatcher.DispatchDelayed |
Map changes
In Xamarin.Forms, the Map
control and associated types are in the Xamarin.Forms.Maps
namespace. In .NET MAUI, this functionality has moved to the Microsoft.Maui.Controls.Maps and Microsoft.Maui.Maps namespaces. Some properties have been renamed and some types have been replaced with equivalent types from Xamarin.Essentials.
The following table shows the .NET MAUI replacements for the functionality in the Xamarin.Forms.Maps
namespace:
Xamarin.Forms API | .NET MAUI API | Comment |
---|---|---|
Xamarin.Forms.Maps.Map.HasScrollEnabled |
Microsoft.Maui.Controls.Maps.Map.IsScrollEnabled | |
Xamarin.Forms.Maps.Map.HasZoomEnabled |
Microsoft.Maui.Controls.Maps.Map.IsZoomEnabled | |
Xamarin.Forms.Maps.Map.TrafficEnabled |
Microsoft.Maui.Controls.Maps.Map.IsTrafficEnabled | |
Xamarin.Forms.Maps.Map.MoveToLastRegionOnLayoutChange |
No .NET MAUI equivalent. | |
Xamarin.Forms.Maps.Pin.Id |
Microsoft.Maui.Controls.Maps.Pin.MarkerId | |
Xamarin.Forms.Maps.Pin.Position |
Microsoft.Maui.Controls.Maps.Pin.Location | |
Xamarin.Forms.Maps.MapClickedEventArgs.Position |
Microsoft.Maui.Controls.Maps.MapClickedEventArgs.Location | |
Xamarin.Forms.Maps.Position |
Microsoft.Maui.Devices.Sensors.Location | Members of type Xamarin.Forms.Maps.Position have changed to the Microsoft.Maui.Devices.Sensors.Location type. |
Xamarin.Forms.Maps.Geocoder |
Microsoft.Maui.Devices.Sensors.Geocoding | Members of type Xamarin.Forms.Maps.Geocoder have changed to the Microsoft.Maui.Devices.Sensors.Geocoding type. |
.NET MAUI has two Map
types - Microsoft.Maui.Controls.Maps.Map and Microsoft.Maui.ApplicationModel.Map. Because the Microsoft.Maui.ApplicationModel namespace is one of .NET MAUI's global using
directives, when using the Microsoft.Maui.Controls.Maps.Map control from code you'll have to fully qualify your Map
usage or use a using alias.
In XAML, an xmlns
namespace definition should be added for the Map control. While this isn't required, it prevents a collision between the Polygon
and Polyline
types, which exist in both the Microsoft.Maui.Controls.Maps and Microsoft.Maui.Controls.Shapes namespaces. For more information, see Display a map.
Other changes
A small number of other APIs have been consolidated in the move from Xamarin.Forms to .NET MAUI. The following table shows these changes:
Xamarin.Forms API | .NET MAUI API | Comments |
---|---|---|
Xamarin.Forms.Application.Properties |
Microsoft.Maui.Storage.Preferences | |
Xamarin.Forms.Button.Image |
Microsoft.Maui.Controls.Button.ImageSource | |
Xamarin.Forms.Frame.OutlineColor |
Microsoft.Maui.Controls.Frame.BorderColor | |
Xamarin.Forms.IQueryAttributable.ApplyQueryAttributes |
Microsoft.Maui.Controls.IQueryAttributable.ApplyQueryAttributes | In Xamarin.Forms, the ApplyQueryAttributes method accepts an IDictionary<string, string> argument. In .NET MAUI, the ApplyQueryAttributes method accepts an IDictionary<string, object> argument. |
Xamarin.Forms.MenuItem.Icon |
Microsoft.Maui.Controls.MenuItem.IconImageSource | Xamarin.Forms.MenuItem.Icon is the base class for Xamarin.Forms.ToolbarItem , and so ToolbarItem.Icon becomes ToolbarItem.IconImageSource . |
Xamarin.Forms.OrientationStateTrigger.Orientation |
Microsoft.Maui.Controls.OrientationStateTrigger.Orientation | In Xamarin.Forms, the OrientationStateTrigger.Orientation property is of type Xamarin.Forms.Internals.DeviceOrientation . In .NET MAUI, the OrientationStateTrigger.Orientation property is of type DisplayOrientation. |
Xamarin.Forms.OSAppTheme |
Microsoft.Maui.ApplicationModel.AppTheme | |
Xamarin.Forms.Span.ForegroundColor |
Microsoft.Maui.Controls.Span.TextColor | |
Xamarin.Forms.ToolbarItem.Name |
Microsoft.Maui.Controls.MenuItem.Text | Microsoft.Maui.Controls.MenuItem.Text is the base class for Microsoft.Maui.Controls.ToolbarItem, and so ToolbarItem.Name becomes ToolbarItem.Text . |
In addition, in Xamarin.Forms, the Page.OnAppearing
override is called on Android when an app is backgrounded and then brought to the foreground. However, this override isn't called on iOS and Windows in the same scenario. In .NET MAUI, the OnAppearing() override isn't called on any platforms when an app is backgrounded and then brought to the foreground. Instead, you should listen to lifecycle events on Window to be notified when an app returns to the foreground. For more information, see .NET MAUI windows.
Native forms changes
Native forms in Xamarin.Forms has become native embedding in .NET MAUI, and uses a different initialization approach and different extension methods to convert cross-platform controls to their native types. For more information, see Native embedding.
Bootstrap your migrated app
When manually updating a Xamarin.Forms app to .NET MAUI you will need to enable .NET MAUI support in each platform project, update each platform project's entry point class, and then configure the bootstrapping of your .NET MAUI app.
Enable .NET MAUI in platform projects
Before you update each platform project's entry point class, you must first enable .NET MAUI support. This can be achieved by setting the $(UseMaui)
build property to true
in each platform project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<UseMaui>true</UseMaui>
</PropertyGroup>
</Project>
Important
You must add <UseMaui>true</UseMaui>
to your project file to enable .NET MAUI support. In addition, ensure you've added <EnableDefaultMauiItems>false</EnableDefaultMauiItems>
to your WinUI project file. This will stop you receiving build errors about the InitializeComponent
method already being defined.
Add package references
In .NET 8, .NET MAUI ships as a .NET workload and multiple NuGet packages. The advantage of this approach is that it enables you to easily pin your projects to specific versions, while also enabling you to easily preview unreleased or experimental builds.
You should add the following explicit package references to an <ItemGroup>
in each project file:
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
The $(MauiVersion)
variable is referenced from the version of .NET MAUI you've installed. You can override this by adding the $(MauiVersion)
build property to each project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<UseMaui>True</UseMaui>
<MauiVersion>8.0.3</MauiVersion>
</PropertyGroup>
</Project>
Android project configuration
In your .NET MAUI Android project, update the MainApplication
class to match the code below:
using System;
using Android.App;
using Android.Runtime;
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using YOUR_MAUI_CLASS_LIB_HERE;
namespace YOUR_NAMESPACE_HERE.Droid
{
[Application]
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
{
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}
Also update the MainActivity
class to inherit from MauiAppCompatActivity
:
using System;
using Microsoft.Maui;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
namespace YOUR_NAMESPACE_HERE.Droid
{
[Activity(Label = "MyTitle", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
}
}
Then, update your manifest file to specify that the minSdKVersion
is 21, which is the minimum Android SDK version required by .NET MAUI. This can be achieved by modifying the <uses-sdk />
node, which is a child of the <manifest>
node:
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="32" />
iOS project configuration
In your .NET MAUI iOS project, update the AppDelegate
class to inherit from MauiUIApplicationDelegate
:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui;
using Foundation;
using UIKit;
using YOUR_MAUI_CLASS_LIB_HERE;
namespace YOUR_NAMESPACE_HERE.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}
Then, update Info.plist so that MinimumOSVersion
is 11.0, which is the minimum iOS version required by .NET MAUI.
UWP project configuration
In your .NET MAUI WinUI 3 project, update App.xaml to match the code below:
<?xml version="1.0" encoding="utf-8"?>
<maui:MauiWinUIApplication
x:Class="YOUR_NAMESPACE_HERE.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui"
xmlns:local="using:YOUR_NAMESPACE_HERE.WinUI">
<maui:MauiWinUIApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</maui:MauiWinUIApplication.Resources>
</maui:MauiWinUIApplication>
Note
If your project included resources in your existing App.xaml you should migrate them to the new version of the file.
Also, update App.xaml.cs to match the code below:
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using YOUR_MAUI_CLASS_LIB_HERE;
namespace YOUR_NAMESPACE_HERE.WinUI;
public partial class App : MauiWinUIApplication
{
public App()
{
InitializeComponent();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
Note
If your project included business logic in App.xaml.cs you should migrate that logic to the new version of the file.
Then add a launchSettings.json file to the Properties folder of the project, and add the following JSON to the file:
{
"profiles": {
"Windows Machine": {
"commandName": "MsixPackage",
"nativeDebugging": true
}
}
}
App entry point
.NET MAUI apps have a single cross-platform app entry point. Each platform entry point calls a CreateMauiApp
method on the static MauiProgram
class, and returns a MauiApp.
Therefore, add a new class named MauiProgram
that contains the following code:
namespace YOUR_NAMESPACE_HERE;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>();
return builder.Build();
}
}
Note
For Xamarin.Forms UWP projects, the App
reference in builder.UseMauiApp<App>()
can be found in the MainPage.xaml.cs file.
If there are platform specific services that need to be migrated to .NET MAUI, use the AddTransient(IServiceCollection, Type) method to add a transient service of the specified type to the specified IServiceCollection.
Note
You can quickly update your Xamarin.Forms
namespaces to Microsoft.Maui
by using Quick actions in Visual Studio, provided that you have Upgrade Assistant installed.
AssemblyInfo changes
Properties that are typically set in an AssemblyInfo.cs file are now available in your SDK-style project. We recommend migrating them from AssemblyInfo.cs to your project file in every project, and removing the AssemblyInfo.cs file.
Optionally, you can keep the AssemblyInfo.cs file and set the GenerateAssemblyInfo
property in your project file to false
:
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
For more information about the GenerateAssemblyInfo
property, see GenerateAssemblyInfo.
Update app dependencies
Generally, Xamarin.Forms NuGet packages are not compatible with .NET 8 unless they have been recompiled using .NET target framework monikers (TFMs). However, Android apps can use NuGet packages targeting the monoandroid
and monoandroidXX.X
frameworks.
You can confirm a package is .NET 8 compatible by looking at the Frameworks tab on NuGet for the package you're using, and checking that it lists one of the compatible frameworks shown in the following table:
Compatible frameworks | Incompatible frameworks |
---|---|
net8.0-android, monoandroid, monoandroidXX.X | |
net8.0-ios | monotouch, xamarinios, xamarinios10 |
net8.0-macos | monomac, xamarinmac, xamarinmac20 |
net8.0-tvos | xamarintvos |
xamarinwatchos |
Note
.NET Standard libraries that have no dependencies on the incompatible frameworks listed above are still compatible with .NET 8.
If a package on NuGet indicates compatibility with any of the compatible frameworks above, regardless of also including incompatible frameworks, then the package is compatible. Compatible NuGet packages can be added to your .NET MAUI library project using the NuGet package manager in Visual Studio.
If you can't find a .NET 8 compatible version of a NuGet package you should:
- Recompile the package with .NET TFMs, if you own the code.
- Look for a preview release of a .NET 8 version of the package.
- Replace the dependency with a .NET 8 compatible alternative.
Compile and troubleshoot
Once your dependencies are resolved, you should build your project. Any errors will guide you towards next steps.
Tip
- Delete all bin and obj folders from all projects before opening and building projects in Visual Studio, particularly when changing .NET versions.
- Delete the Resource.designer.cs generated file from the Android project.
The following table provides guidance for overcoming common build or runtime issues:
Issue | Tip |
---|---|
Xamarin.* namespace doesn't exist. |
Update the namespace to its .NET MAUI equivalent. For more information, see Namespace changes. |
API doesn't exist. | Update the API usage to its .NET MAUI equivalent. For more information, see API changes. |
App won't deploy. | Ensure that the required platform project is set to deploy in Visual Studio's Configuration Manager. |
App won't launch. | Update each platform project's entry point class, and the app entry point. For more information, see Bootstrap your migrated app. |
CollectionView doesn't scroll. | Check the container layout and the measured size of the CollectionView. By default the control will take up as much space as the container allows. A Grid constrains children at its own size. However a StackLayout enables children to take up space beyond its bounds. |
Pop-up is displayed under the page on iOS. | In Xamarin.Forms, all pop-ups on iOS are UIWindow instances but in .NET MAUI pop-ups are displayed by locating the current presenting ViewController and displaying the pop-up with PresentViewControllerAsync . In plugins such as Mopups, to ensure that your pop-ups are correctly displayed you should call DisplayAlert, DisplayActionSheet, or DisplayPromptAsync from the ContentPage that's used inside the Mopup popup. |
BoxView not appearing. | The default size of a BoxView in Xamarin.Forms is 40x40. The default size of a BoxView in .NET MAUI is 0x0. Set WidthRequest and HeightRequest to 40. |
Layout is missing padding, margin, or spacing. | Add default values to your project based on the .NET MAUI style resource. For more information, see Default value changes from Xamarin.Forms. |
Custom layout doesn't work. | Custom layout code needs updating to work in .NET MAUI. For more information, see Custom layout changes. |
Custom renderer doesn't work. | Renderer code needs updating to work in .NET MAUI. For more information, see Use custom renderers in .NET MAUI. |
Effect doesn't work. | Effect code needs updating to work in .NET MAUI. For more information, see Use effects in .NET MAUI. |
SkiaSharp code doesn't work. | SkiaSharp code needs minor updates to work in .NET MAUI. For more information, see Reuse SkiaSharp code in .NET MAUI. |
Can't access previously created app properties data. | Migrate the app properties data to .NET MAUI preferences. For more information, see Migrate data from the Xamarin.Forms app properties dictionary to .NET MAUI preferences. |
Can't access previously created secure storage data. | Migrate the secure storage data to .NET MAUI. For more information, see Migrate from Xamarin.Essentials secure storage to .NET MAUI secure storage. |
Can't access previously created version tracking data. | Migrate the version tracking data to .NET MAUI. For more information, see Migrate version tracking data from a Xamarin.Forms app to a .NET MAUI app. |