Microsoft has released its long-awaited successor to Xamarin, dubbed .Net MAUI. After months of speculation, Microsoft’s new development framework will be the key to creating mobile and cross-platform applications on the .NET platform. New features, performance benchmarks, release date and more. Here’s all what you need to know about it!
What is .NET MAUI?
For those who don’t know what is .NET MAUI:
.NET MAUI means .NET Multi-Platform App User Interface (MAUI) and allows us to build native desktop and mobile apps with a single code base. .NET MAUI will be running on .NET 6 (and .NET 7).
According to Microsoft, .NET MAUI is the evolution of Xamarin.Forms, extended from mobile to desktop scenarios, with UI controls rebuilt from scratch for performance and extensibility.
.NET MAUI stands out for its ability to unify APIs from different platforms (macOS, Android and Windows) into a single API. This will allow developers to have a unified and more comfortable experience while providing great control over all the functions of each platform (and this is something very cool).
After many people said that it arrives to replace Xamarin, Microsoft had to come out and say that .NET MAUI is complementary to Xamarin.
.NET MAUI Release Date
If you are wondering if is .NET MAUI production ready or if is .NET MAUI released, yes, you can now use .NET MAUI to develop cross-platform applications. Microsoft released on April 12, 2022 the first Release Candidate of .NET MAUI and on April 26 they released Release Candidate 2.
As these releases are under Microsoft’s “go-live” support policy, support from Microsoft is already active for production applications developed with .NET MAUI.
Getting Started with .NET MAUI
Support
If we start by introducing .NET MAUI, .NET 6 will be released in November 2021 and will be supported for three years, as a Long Term Support (LTS) release. The platform matrix has been significantly expanded compared to .NET 5.
The additions are:
- Android.
- iOS.
- Mac and Mac Catalyst, for x64 and Apple Silicon (AKA “M1”).
- Windows Arm64 (specifically Windows Desktop).
.NET 6 Debian container images are based on Debian 11 (“bullseye”), which is currently in testing.
Startup
The .NET MAUI applications will use a Startup class that will allow:
- Configure method to pipe service registration, handler registration, or application customization processes.
- Be able to create a custom HostBuilder.
For instance 👇
public void Configure(IAppHostBuilder appBuilder)
{
appBuilder = appBuilder
.UseCompatibilityRenderers()
.UseMauiApp<MyApp>();
}
By default, if you don’t want to customize anything special, or you want to use your own dependency container or something, you can.
Accessibility
Adding more control and improving the accessibility API to avoid confusion in addition to aligning the behavior in all cases and platforms is one of the priorities in one of the sections with such importance as accessibility.
<Entry
Text="Entry text TH"
FontSize="14"
SemanticProperties.Description="Description text"
SemanticProperties.Hint="Hint text"/>
The concept of SemanticProperties is added. Microsoft are talking about a series of properties that add extra information to Views to allow it to correctly interpret what happens when using the screen reader, or keyboard navigation.
Workload Installation
As part of .NET unification, Microsoft have introduced the concept of SDK workloads to enable specific developer scenarios on top of the .NET SDK. In previous preview the underlying SDKs for iOS, Mac Catalyst, macOS, Android were enabled. Now they are introducing the maui, maui-desktop, maui-mobile and workloads. The first will acquire and install all the required SDKs for building .NET MAUI applications.
In the near future Visual Studio 2022 will include these with its installer.
If you want use them, just open a CLI and check what you have installed 👇
dotnet sdk check
After verifying what’s installed, you can see how the additional workloads are running 👇
dotnet workload list
Finally to install .NET MAUI you need to execute 👇
dotnet workload install maui
.NET MAUI New Features
Introducing .NET MAUI features: Controls, UI/UX designs, .NET MAUI toolkit with benchmarks and examples at the end.
.NET MAUI Controls
Ecosystem Controls
DevExpress, Syncfusion, and Telerik have all recently released new sets of controls for.NET MAUI that take use of Microsoft’s strong graphics capabilities. Maui.Graphics.
BlazorWebView
The new BlazorWebView lets you host a Blazor web application directly in your application and take advantage of native platform functionality and user interface controls. The control can be added to any XAML page and pointed to the root of the Blazor application (It’s also often called Blazor Hybrid or Blazor Desktop).
<BlazorWebView
HostPage="wwwroot/index.html"
Services="{StaticResource Services}">
<BlazorWebView.RootComponent>
<RootComponent
Selector="#app"
ComponentType="{x:Type local:Main}"
/>
</BlazorWebView.RootComponent>
</BlazorWebView>
Slim processors
Also .NET MAUI will have a function to migrate a custom renderer from Xamarin.Forms. Although these can be used with some compatibility package, Microsoft claims that this will help the application to be much lighter and to develop it much more efficient.
dotnet build -t:Run -f net6.0-android
dotnet build -t:Run -f net6.0-ios
dotnet build -t:Run -f net6.0-maccatalyst
Single Project and Windows
Microsoft have made a few updates to single project based on developer feedback and Windows support to adopt the latest features.
- The NuGet package is replaced with the .NET MAUI workload (
<UseMaui>true</UseMaui>
in the .csproj). - Single project solutions now nest individual platforms within a “Platforms” folder for tidy organization.
- Updated to Windows App SDK 0.8.1 RC. Use the latest Visual Studio 2022 compatible extension from the marketplace.
UX/UI .NET MAUI Featues
ImageButton
The ImageButton
view can combine a Button and an Image into one button. When someone clicks the ImageButton
, it does something different than if they click a Button. It has no idea of what is written on the text and how it is displayed, as opposed to the Button view.
WebView
WebView
renders any online or embedded HTML material using the platform’s native browser control; suitable for displaying markup that is more complicated than the subset of HTML supported by Label
.
BoxView
BoxView
is a basic rectangle with a given width, height, and color. It could be used for BoxView
decorating, basic graphics, and touch interaction with the user.
IndicatorView
The IndicatorView
is a control that shows indications in a CarrouselView
that reflect the number of items and the current position:
Shadows, corners, and borders
Here we have Microsoft.Maui.Graphics
library, that offers an uniform UI drawing API based on native graphics engines, allowing us to quickly add borders, corner rendering, and gorgeous shadows to nearly any .NET MAUI layout or control.
Microsoft offers a new border
control. It may be used to provide borders and individual corner management on any layout or control. This functionality is accessible in WPF, UWP, Silverlight, and the most recent Windows App SDK templates.
In this example, we can see how is used a border check to wrap the counter label in order to round the top-left and bottom-right corners. This is an excellent choice for small business owners that are downsizing or wanting to create a more minimalist appearance on their new site.
<Border
Grid.Row="2"
Padding="16,8"
Stroke="{StaticResource PrimaryBrush}"
Background="#2B0B98"
StrokeThickness="4"
HorizontalOptions="Center">
<Border.StrokeShape>
<RoundRectangle CornerRadius="40,0,0,40"/>
</Border.StrokeShape>
<Label
Text=".NET MAUI Preview: 9"
FontSize="18"
FontAttributes="Bold"
TextColor="White"
x:Name="CounterLabel" />
</Border>
The specified shape’s corner radius accepts a Thickness
type value, allowing separate control of each of the rectangle’s four corners: bottom-left, bottom-right, top-left and top-right.
The border
control can make your content wrap around. You can customize the background color and padding. There are more attributes that you can change, including:
- StrokeLineCap: is a form that appears at the end of a line.
- StrokeDashOffset: is the distance between the dots in the dash pattern.
- StrokeMiterLimit: set the miter length ratio to half of the stroke thickness.
- StrokeLineJoin: a type of vertices join.
- StrokeDashArray: a dash and gap pattern in the stroke.
Are you ready to give your user interface some depth? Any layout or control, including pictures and objects, can be given with Shadow
👇
<Image>
<Image.Shadow>
<Shadow Brush="#000000"
Offset="20,20"
Radius="40"
Opacity="0.8"/>
</Image.Shadow>
</Image>
This is the result:
Shared fonts, images, and app icons
Fonts and images can be placed in one location in your solution and .NET MAUI will enable them to natively work on all platforms you target. These are tracked in your *.csproj as SharedImage
and SharedFont
.
<ItemGroup>
<SharedImage Include="appicon.svg" ForegroundFile="appiconfg.svg" IsAppIcon="true" />
<SharedFont Include="Resources\Fonts\ionicons.ttf" />
</ItemGroup>
Both accept wildcards to include all files within a location.
<ItemGroup>
<SharedImage Include="appicon.svg" ForegroundFile="appiconfg.svg" IsAppIcon="true" />
<SharedImage Include="Resources\Images*" />
<SharedFont Include="Resources\Fonts*" />
</ItemGroup>
Font Scaling
All controls across all platforms now have font scaling enabled by default. This means as your application users adjust their text scaling preferences in the OS, your UI will reflect their choice. This produces a more accessible app by default.
Each control has an added FontAutoScalingEnabled
, and it even works with FontImageSource
or your font icons. Setting a FontSize
is your 100% size, and to lock it in you’ll set:
FontAutoScalingEnabled = "false"
<VerticalStackLayout>
<Label
Text="Scaling disabled"
FontSize="18"
FontAutoScalingEnabled="False"/>
<Label
Text="Scaling enabled"
FontSize="18"/>
</VerticalStackLayout>
New Layouts
Microsoft also tells us that the layouts that have been used in the .NET MAUI are the Xamarin.Forms layouts. They say they started with that approach to quickly get the user interface on screen and focus on completing their library of UI 40 controls.
At the same time, they have been creating streamlined layouts based on a new LayoutManager approach that employs its long 7 years of Xamarin.Forms design training to optimize consistency, performance, and maintainability.
One of the updates that you may have noticed is the leveling out of the default spacing values in these layouts: 0. If you’ve used the legacy layouts, then you already know the different arbitrary values previously set there. Zero sets a clearer expectation and prompts you to set your preferred values that best suit your design needs.
A very easy way is 👇
<ResourceDictionary>
<Style TargetType="StackLayout">
<Setter Property="Spacing" Value="6"/>
</Style><Style TargetType="Grid">
<Setter Property="ColumnSpacing" Value="6"/>
<Setter Property="RowSpacing" Value="6"/>
</Style>
</ResourceDictionary>
Native Alerts
Each platform has a native way of displaying alerts to users. These can be simple informational popups, simple input forms, and even action sheets with multiple options to guide a user.
These are available from any Page in a .NET MAUI application. 👇
await DisplayAlert ("Alert", "You have been alerted", "OK");
Clipping
When you need to mask content you can now add shapes to the clipping region of a layout or view. The most common use for this is to make a circle image.
Gestures
Gesture recognizers allow you to apply tap, pinch, pan, swipe, and drag-and-drop to any view instance. You can apply them easily in XAML.
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="2" Command="{Binding OnTileTapped}"/></Grid.GestureRecognizers>
<!-- Grid content -->
</Grid>
Splash Screen
On mobile platforms especially you want your first screen to appear as quickly as possible, and this is done by implementing a static splash screen. .NET MAUI now has a single place to describe your splash screen for all platforms that support them.
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" />
New Control Handlers
They have introduced the first controls and properties that implement a new handler approach. These include partial implementations of Button, Label, and Entry, Slider, and Switch. They are now accepting pull requests to fill out complete implementations, and several contributors have already successfully contributed.
The HelloMaui sample application now runs from a single project to macOS, iOS, and Android showcasing the current set of ported controls.
macOS
iOS
Android
Windows Control Styling (Fluent Design System)
Here, David Ortinau — The Principal Program Manager at .NET MAUI — tells us that they have added design changes, now with a more fluid interface and new controls and support for themes. The main updates are:
Multi-window Apps
Here is one of the most important and main features of this Preview. Now with .NET MAUI you can add multiple windows. Simply with Application.Current.Windows
you can open a new window, because it contains the references of the created windows.
Let’s look at the Microsoft example:
var secondWindow = new Window {
Page = new MySecondPage {
// ...
}
};
Application.Current.OpenWindow(secondWindow);
New Navigation in .NET MAUI (Shell)
What is this from Shell? Shell (also known as AppShell
) facilitates simple application designs, especially in tabs and drop-down menus.
Simply add the pages to your app and then arrange them as you like within the navigation structure. Let’s see how nice it looks:
To be honest, I think these new features are pretty cool.
Shell and Dependency Injection
In this new feature Microsoft tells us a bit about HostBuilder
. With this, .NET MAUI will have a powerful dependency injection. What Shell mainly offers is an incredible templating and styling capability to achieve in a very simple way our needs (or what we require at that moment).
To see it in a more practical way, let’s look at this example:
As Microsoft tells us, we must define dependencies in the DI container.
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>();
builder.Services
.AddSingleton<MainViewModel>();
return builder.Build();
}
}
And after that, we simply add in the page where we want the previously defined dependencies to be injected:
public partial class MainPage
{
readonly MainViewModel _viewModel;
public MainPage(MainViewModel viewModel)
{
InitializeComponent();
BindingContext = _viewModel = viewModel;
}
}
Very simple, right? Let’s continue
Unification of libraries in .NET MAUI
As Microsoft tells us, .NET MAUI will come with a unification of critical libraries. You will provide several benefits by merging the Xamarin.Essentials library into the .NET MAUI so that with these, you can easily use the device’s capabilities such as device sensors, photos, contacts, and many services that you use on a regular basis, such as authentication and secure storage.
Mac Catalyst
You can add the following TargetFramework settings to your project to build for macOS desktop, using Mac Catalyst.
<TargetFrameworks>net6.0-android;net6.0-ios</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">$(TargetFrameworks);net6.0-maccatalyst</TargetFrameworks>
.NET 6, C# 10 and Hot Reload
Templates and C# 10
I think the phrase with which Microsoft introduces this feature is perfect:
“Simplification is one of the main goals of .NET MAUI”
To do this, they have added the templates using C# patterns, both file-scoped namespaces and implicit usings. Besides, they have added new element templates, with which we (the developers) will save a lot of work. Let’s see how it works (again I find the Microsoft example perfect):
namespace Preview11;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
return builder.Build();
}
}
At this point you will think:
Where are the using statements?
Relax, don’t worry — Microsoft says that, not me. From now on, with this new update implicit global usings will be used to gather them dynamically.
.NET Hot Reload
.NET Hot Reload is a new feature, which according to Microsoft, will allow you to make live edits to the source code of your application while it is running, reducing the number of times you need to rebuild your application.
To start testing this feature install both .NET 6 Preview 4 and Visual Studio 2019 version 16.11 Preview 1. Start your app through the Visual Studio debugger (F5) targeting a WinUI 3 host. Once your app is running, you’ll now have the new option to make code changes and apply them using our new “apply code changes” button as illustrated below.
They also tell us that in the next releases .NET Hot Reload will also be available for Android, iOS and macOS, and will also integrate XAML Hot Reload and Live Visual Tree.
.NET MAUI Performance with Benchmaks
Android Quick Start
Ahead-of-time (AOT) compilation helps your Android application to code faster (high performance). If you’re trying to stay below the wifi installation bar, then full AOT may make your app’s artifacts larger than you want. Startup tracing is a solution in this case.
You can balance performance and space by only partially AOT’ing the parts of your program that run at startup
The following are the results of device testing on the Pixel 5:
400ms benchmark
Here we can see an incredible increase in the performance made by Jonathan Peppers.
He found a systemic problem with Xamarin.Android class libraries:
- Include AndroidX & Google Material
- Include at least one
@(AndroidResource)
and use the ID from C# Resource.designer.cs
has 2,700+ fields
This problem compounds itself as you include more class libraries that
depend on each other. The main app will end up repeatedly setting
these fields at startup for each library that contains fields inResource.designer.cs
…
Reviewing the .NET MAUI fields, Jonathan Peppers found:
src\Core\src\obj\Debug\net6.0-android\Resource.designer.cs
5310
src\Controls\src\Core\obj\Debug\net6.0-android\Resource.designer.cs
5167 fields
src\Controls\src\Xaml\obj\Release\net6.0-android\Resource.designer.cs
5167 fields
src\Compatibility\Core\src\obj\Debug\net6.0-android\Resource.designer.cs
5333 fields
src\Essentials\src\obj\Debug\net6.0-android\Resource.designer.cs
204 fields
He found 21,497 fields were set at startup for a dotnet new maui
app in Resource.designer.cs
To solve this problem, he came up with a new pattern.
He only copy the contents of Resource.designer.cs
and manually delete
all the fields we don’t need.
Results
Building a dotnet new maui
then dotnet build -c Release
and
running on a Pixel 5.
Before:
- 21,497 fields set at startup in
UpdateIdValues()
- Activity Displayed: 1s454ms
- .apk size: 17300275 bytes
After:
- 65 fields set at startup in
UpdateIdValues()
- Activity Displayed: 1s079ms
- .apk size: 16677683 bytes
You can check the benchmark at GitHub
.NET MAUI RELEASE CANDIDATE Features
Microsoft is now officially releasing the .NET MAUI Release Candidates. All of them with new features and functionalities offering official support from Microsoft to the applications developed in .NET MAUI. Discover all the latest news!