MAUI Ebook - Migration
MAUI Ebook - Migration
MAUI Ebook - Migration
NET MAUI
When and How to Transition
to Cross-Platform App Development
EBOOK
Table of Contents
Introduction / 4 Part 3: Migration of Xamarin ERP App to
.NET MAUI / 15
Part 1: Should You Migrate from Xamarin. 1. Run the Dotnet Upgrade Assistant / 15
Forms to .NET MAUI? When? / 4 2. Create a Blank .NET MAUI App / 16
The Benefits of Migrating to .NET MAUI / 5 3. Add Third-Party References / 16
Easier Development and Benefits for the Team / 5 4. Move Independent Code / 18
1. .NET MAUI Is Part of .NET / 5 Login and Authentication / 18
2. Better Tooling / 5 5. Pages and Themes, or the XAML Part / 19
3. Frequent Upgrades and Addressing Developer Base Classes and Data Context / 19
Feedback / 6 Raplacing Telerik UI / 19
4. Command Line Support / 6 6. Consider the Images / 20
5. Simple Project Structure / 6 7. ViewModels / 21
6. Better Customization / 6 8. AuthenticationService and NavigationService / 22
7. Better Handling of Resources in .NET MAUI / 7 Register the Services / 23
8. Inclusion of Graphics / 8 9. Migrating Datamodels and Services / 24
9. Unification of Libraries / 8 11. MauiSplash Screen & Icon / 27
10. Modern Patterns / 8 Conclusion / 28
Benefits for the App / 9
11. Continuous Performance Improvements / 9 Part 4: How to Migrate Xamarin.Forms
12. Better Accessibility Support / 9 Renderers to .NET MAUI Handlers? Should
13. Multiple Windows and More to Expect / 9 We? / 28
14. Desktop & Blazor Support Is Also Important / 9 What Are the Options? / 29
Are There Any Cons if I Migrate? / 10 So, How to Choose? / 29
Is .NET MAUI Mature Enough for a Production App / 10 Option 1: Continue to Use the Same Renderers / 29
Is There Any Risk if I Do Not Migrate or Delay 1. Move the Files to the Right Place / 30
Migration? / 11 Xamarin.Forms vs. .NET MAUI files / 30
2. Modify the Code a Little Bit / 30
Part 2: Things to Consider When Planning 3. Register the Renderers / 31
Your Migration from Xamarin.Forms to .NET Option 2: Using Handlers and Mappers / 32
MAUI / 12 What Are These Handlers? / 32
1. Install VS 2022 and Set up Your .NET MAUI What Are Mappers? / 32
Environment / 12 Scenario 1: Access the Handler When You Need
2. Review Data Models and Patterns of Your Existing to Modify It / 33
App / 13 Scenario 2: Use Handler Lifecycle Events to Access It and
3. Choose a Navigation Pattern / 13 Modify Properties of the Components / 34
4. Check Whether Your Third-Party Libraries Support .NET Scenario 3: Create a Custom Component and a New
MAUI / 14 Handler / 34
5. Azure Support / 14 Conclusion / 34
6. Take a Minute to Consider the Future of Windows
Support / 14
7. Have You Used Custom Renderers to Customize the
Native Controls? / 15
Conclusion / 55
About The Author / 56
Rossitsa Fakalieva / 56
Cross-platform also brings the promise of numerous benefits for the developer experience.
Improved performance, single code base compatible with various platforms, easy
deployment—all enticing perks that will save you development time worth countless
human hours.
So, what if you have your business apps built with Xamarin? Should you upgrade to .NET
MAUI and, if so, when? If you have a stable app and are not planning to add updates to it,
you may be years aways from the point that requires you to plan a migration.
But what if your app does need an update right now? This guide will help you examine the
benefits of migrating to .NET MAUI from Xamarin.Forms for the dev experience, the app
and its end users, plus any downsides, so you can decide if and when migration is right for
your app.
I want to explore the right way to decide whether migration from Xamarin.Forms to .NET
MAUI is the right path for your code, team and application and whether you should
consider it.
This is the major change—the architecture of the new framework is designed by Microsoft
with the main goal of being integrated into .NET and simply being better than Xamarin.
Forms.
.NET Multi-platform App UI (.NET MAUI) is integrated into .NET, while Xamarin is not,
although it is still part of .NET Core 3.1. So, due to the integration of .NET 6, 7 and 8, you
can use the new C# and .NET features in .NET MAUI for your enterprise development.
Starting with .NET 7, .NET MAUI will align with the .NET release cadence—that is, .NET
MAUI 7.0 will ship with .NET 7.0, .NET MAUI 8.0 ships with .NET 8.0, and so on.
2. Better Tooling
VS 2022 and VS 2022 for Mac install the MAUI workloads directly and take care of the
smooth dev experience. Coming as part of VS installer, installing and updating .NET MAUI
is way easier for engineers.
With VS 2022, there are also AI-assisted code suggestions like IntelliCode, which gives
developers a powerful set of automatic code completions that understand the .NET MAUI
app UI and code. When a dev starts typing, it will understand the code context, variable
names, functions, and even provide better IntelliSense and suggest whole line completions.
Currently, .NET MAUI is one of the key technologies that Microsoft is focused on and
there are a lot of channels that MS is using to gather feedback and address it. This is great
because if there is something you do not like, you have power as a developer to let them
know—write feedback or contribute to the repo, which is very active.
Another advantage of using .NET MAUI is that it runs on .NET CLI. The .NET command-
line interface (CLI) is a cross-platform toolchain for developing, building, running and
publishing .NET apps.
Honestly, this is my favorite. If you have ever used Xamarin.Forms, you probably know that
it uses separate projects for each target platform. With .NET MAUI, you will no longer have
this problem as here all the platforms can easily be managed in a single project. To create
a .NET MAUI project, you can find all necessary features like fonts, app icons, images,
styling, raw assets and splash screen in the Resources folder. .NET MAUI will do the rest by
optimizing them for each platform’s specific requirements.
This also makes it easier to share not only resources but tests too.
6. Better Customization
.NET MAUI is coming with a completely new architecture. It has two main purposes—
performance optimizations and decoupling of custom code from the native UI. With
this change, it’s easier to add support of new platforms even when they need custom
experience.
.NET MAUI introduces a new abstract layer of control interfaces. And a new concept, called
Handlers, which depend only on interfaces, but not on the implementation of UI controls:
partial class
EntryHandler.ios.cs
EntryHandler.android.cs
platform-specific
To customize the behavior, we can now write our own handler classes and mappers instead
of renderers.
This makes the developer’s life easier—we can easily modify the handler to exclude/
include more platforms. This is a great feature having in mind that adding a new OS is
always an option.
With .NET MAUI, we can manage the resources more easily too. As a result of the SDK
style project, there is a folder named Resources, under which SVG images are included and
used as the image source and splash screen.
8. Inclusion of Graphics
In Xamarin.Forms, you cannot find any direct APIs for drawing graphics. However, with
.NET MAUI, the situation is different: its cross-platform graphics functionality offers a
drawing canvas for painting and drawing shapes. Graphics modes such as paint, winding
and blend are available. A nice scenario is also the better approach for handling images
with Graphics.
9. Unification of Libraries
.NET MAUI is also one step closer to other modern frameworks introducing MVU and RxUI
support together with one of developers’ favorites—the MVVM pattern.
The Microsoft teams developing the .NET stack are focused on improving performance.
They are committed to this, and .NET MAUI is no exception to this rule. MS improved the
performance by introducing the new architecture and the handlers concept, but the .NET
MAUI team is also committed to continuing improvements in this area. Read more about
.NET MAUI performance here.
With Semantic properties, developers can define information about which controls should
receive accessibility focus and which text should be read aloud to the user. Semantic
properties are attached properties that can be added to any element to set the underlying
platform accessibility APIs. This will make your .NET MAUI app more accessible compared
to its Xamarin.Forms version.
This is just one of the recent features that Microsoft added to .NET MAUI, which was
really missed and needed for desktop behavior. This again shows the commitment to the
development of this framework and that it is here to stay.
Targeting MacOS and Windows desktop users for real, .NET MAUI is not just a mobile
framework that runs on Windows, but a cross-platform framework focused on the desktop
experience. Multi-windows, context menus and many more features are added to .NET
MAUI to allow this.
With Blazor and .NET MAUI Blazor Hybrid apps, you can really extend your existing code
to fit your needs—you can reuse Blazor code and offer a real desktop experience with
unified UI to all devices as Blazor components are able to access native APIs from code
behind!
1. There are some unsupported platforms such as WPF, UWP and Android versions less
than 21. They are unsupported for a reason—Windows support now relies on WinUI and
the Android version is quicky increasing.
2. There is also a learning curve during the migration, but we are here to help—the
following chapters in this guide should help you understand how you can handle the
learning curve.
3. And, of course, consider the time cost. Should you use the time of your team for
migration or for developing new features of the existing Xamarin.Forms app? There is no
right answer here as this depends on your app, but I hope this guide will help you estimate
the migration time and possibly speed it up.
Another important area to this matter is the fact that a lot of third-party APIs, such as
Progress® Telerik®, now provide their version supporting .NET MAUI.
All of these make .NET MAUI not just a good choice for a production app, but a “must-do”.
As a conclusion, I believe the natural path of every Xamarin.Forms app is .NET MAUI, but
the final decision is yours.
If you decide to migrate, we will now go into more detail about how to migrate your
current Xamarin.Froms app based on a Progress Telerik demo application.
In short, these are the things that are good to consider before starting:
• Prepare your environment
• Review DataModels
• Choose a navigation pattern
• Analyze third-party libraries
• Benefit from Azure support
• Take a minute to think about Windows UI and the desktop experience
• Leave customization until the end
• A Mac that is compatible with the latest version of Xcode. For more information, see
Apple’s minimum requirements documentation.
Note: The full list of prerequisites can be found on Microsoft’s documentation site—check
it out for the latest updates.
Another important tool that we will use during the migration is .NET Update Assistant. You
can download it too from VS MarketPlace, but I still recommend you use it via cmd as the
extension has some limitations. You can install it with the following command:
If you’re already using MVVM in your app, it is more natural to stay on it. It’s a great
and widely used pattern. But if this is the case, there are some other important notes to
consider if you use one of the popular MVVM helper libraries:
MVVM cross is popular for Xamarin, but currently not supported with .NET MAUI. As an
alternative, you can rely purely on the built-in MVVM MAUI support or consider using the
MVVM Community toolkit.
One such library is Progress® Telerik® UI for Xamarin and you’ve used it in your apps—
don’t worry—you can safely replace it with Telerik® UI for .NET MAUI.
5. Azure Support
Where is your data service published? What kind of login authentication do you have?
Take a moment to consider the usage of Azure for all of these if you still haven’t.
If your mobile version already uses Azure, an important note is that Microsoft.
WindowsAzure.MobileServices are now rebranded as Microsoft Datasync.Client. Read
a full explanation and get a sample in Microsoft’s docs: Build a .NET MAUI app with Azure
Mobile Apps | Microsoft Learn. We will revisit this topic again in one of our next chapters
where we integrate a Telerik UI for .NET MAUI-built app and Azure mobile.
So, plan the migration of Azure references as a separate step and read the relevant
resources before that.
There are some API changes when migrating from Xamarin.Forms to .NET MAUI. We will
review them in the next two chapters, explaining how we managed to migrate an ERP app.
Part 3: Migration of
Xamarin ERP App to .NET
MAUI
Now it’s time to do the “dirty” job and actually migrate a real app. I’ve taken a complex real-
world app—Telerik Xamarin ERP—built with Telerik UI components.
The solution itself contains two major projects—web service telerikErpService.sln and
Xamarin.Forms app TelerikErp.sln. Let’s leave the service for now as it is a general .NET
app and focus on the Xamarin part.
Rosit\Documents\ERP\app|ErpApp.sln --non-interactive
The tool will back up the app, convert it to .NET 7, rename the Microsoft.Namespaces. with
the Microsoft.Maui and Microsoft.Maui.Controls namespaces.
For the UI part, it is easy—now we will use Telerik UI for .NET MAUI, the UI suite that is
identical to the one we have built the ERP with—just supporting the framework we need.
You can download it here or directly as a NuGet from Telerik NuGet Server.
MVVM Cross does not support .NET MAUI, but the good news is that .NET MAUI itself
gives us all we need to replace it. Still, to make the migration easier, I will use the MVVM
Community toolkit, which gives me similar classes as MVVM Cross library.
And to compare:
Then I moved the Serialization folder with all classes. The interesting part here is the usage
of Colors API.
and all xaml from the themes folders from the original app to my new app.
Now we will inherit from a simple ContentPage and set the BindingContext
in the constructor:
Replacing Telerik UI
When we used Progress Telerik UI for Xamarin, we used to use separate NuGets and
different namespaces for every respective assembly.
Now we are going to use one package and the telerik scheme, which is way more
convenient. This way, we do not have to remember what component belongs to which
assembly.
clr-namespace:Telerik.XamarinForms.*;assembly=Telerik.XamarinForms.*
with:
http://schemas.telerik.com/2022/xaml/maui
This approach is still working in .NET MAUI so we can move it directly. However, we can
benefit from the new resources mechanism. To do that, we can move the images under the
shared Resources/Images folder, which now every .NET MAUI project has. This will
automatically set the build action of the image to MauiImage, and we can shorten the code
to:
7. ViewModels
The ViewModels in the original app inherits from MvxViewModel class of the
MVVM cross library, which now we don’t have access to. That is why we are going to
replace it with ObservableObject using the MVVM community toolkit.
For reference:
As for the NavigationService, we have more things to do. The Xamarin.Forms app uses
MVVM cross navigation service, TabbedPage and NavigationPages.
Now, .NET MAUI has more capabilities to this without third-party services and we will use
the built-in features of the framework. Shell is also the recommended approach for .NET
MAUI apps and so we will replace that too using Shell Tabs. Then we will build our own
simple NavigationService to work with Shell.
C#
public class NavigationService:INavigationService
{
public NavigationService() { }
}
public Task NavigateToAsync(string route, IDictionary<string,
object> routeParameters =
null)
{
return
routeParameters != null
? Shell.Current.GoToAsync(route, routeParameters)
: Shell.Current.GoToAsync(route);
}
C#
await
this.navigationService.NavigateToAsync(“//AboutPage”);
C#
Note that to navigate between pages, we need to register them as route in XAML or in
code behind like this:
<TabBar>
<ShellContent Title=”Login” Route=”LoginPage”
ContentTemplate=”{DataTemplate pages:LoginPage}”
/>
<ShellContent Title=”About” Icon=”About.png”
ContentTemplate=”{DataTemplate pages:AboutPage}”
Route=”AboutPage”/>
</TabBar>
XML
While we relied on MVVM cross in the Xamarin.Forms version of the app, it is now time to
do this ourselves. .NET MAUI allows us to do it easily with the built-in dependency
injection, so I am just adding the following code to MAUIprogram.cs:
builder.Services.AddSingleton<IAuthenticationService,
AuthenticationService>();
builder.Services.AddSingleton<INavigationService,
NavigationService>();
C#
App.cs
C#
LoginPageViewModel.cs (how to access the services):
this.authService = App.Services.GetService<IAuthenticationServi
ce>();
C#
If you made all changes to both pages and their respective viewmodels, now we can build
our app and test it. It will look like this:
And then we are focusing on moving the ErpService and using DataSync.
Replace namespace:
C#
With:
Microsoft.Datasync.Client
Microsoft.Datasync.Client.SQLiteStore
C#
Here are the two APIs that will help you do the replacement. In my opinion, a better
approach here is to consider and write the service from scratch following the Microsoft
documentation.
Note: If your web service application is several years old, it is best to consider updating it
first as it may not be compatible with using DataSync client. Again, refer to MS docs here
and here for more details.
IMobileServiceSyncTable<Vendor> IRemoteTable<Vendor>
DeleteAsync DeleteItemAsync
InsertAsync InsertItemAsync
UpdateAsync ReplaceItemAsync
ToEnumerableAsync ToAsyncEnumerable
this.client.SyncContext.InitializeAsync(store, new
ErpMobileServiceSyncHandler());
//this.CurrentClient.
this.vendorTable = client.GetSyncTable<Vendor>();
C#
.NET MAUI
Xamarin
.NET MAUI
builder.Services.AddSingleton<IErpService, ErpService>();
C#
Still, here we need help from a friend—our UX designer to give us .svg files instead of
.png.
Note also that if you run the app on Windows, the splash screen will not appear. Do not
search for an error, it is simply not supported for now in WinUI.
The time needed for such a migration is not a constant, as it depends on many factors, but
I hope this guide will help you plan the major parts.
Again, here they are for our app: replacing the MVVM API, changing the Navigation API,
rewriting the connection with Azure services, and the easiest transition—replacing Telerik
UI for Xamarin with Telerik UI for .NET MAUI.
After having ported our Xamarin project to .NET MAUI, we now need to sort out the topic
of platform customization.
In Xamarin.Forms, one of the main tools available to you is custom renderers. So how do
you achieve the same functionality in .NET MAUI? Let’s see:
• What are the options?
• Which one to choose?
• Details for both options
• Option 1: Move the code – transfer our old code with some modifications but using
the same renderers
• Option 2: Rewrite renderers to handlers – use the new API and architecture that
.NET MAUI offers us, handlers and mappers
Bear in mind that keeping renderers is not a good solution in the long term as the new
approach is there for a purpose. Handlers and mappers are the result of the new and
better architecture of .NET MAUI, which brings us performance improvements and easy
support for new platforms.
However, one important thing to consider also—not all Microsoft custom renderers are
ported to the new technology as a Cell or ListView. In this case, if you use them, you
simply do not have a choice—your custom renderer must stay for now. However, such
components are rarer and rarer—check them out in the Microsoft article here.
For example, if we want to customize the entry control, we will have the same custom
MyEntry.cs class to inherit the Entry and custom renderer for every affected platform:
Any reference to Xamarin.Forms.* namespaces needs to be removed, and then you can
resolve the related types to Microsoft.Maui.*.
[assembly: ExportRenderer(typeof(MyEntry),
typeof(XamarinRendererProject.UWP.MyEntryRenderer))]
namespace XamarinRendererProject.UWP
C#
using Microsoft.Maui.Controls.Compatibility.Hosting;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder .UseMauiApp<App>()
.UseMauiCompatibility()
.ConfigureFonts(fonts => { fonts.AddFont(“OpenSans-Regular.
ttf”, “OpenSansRegular”); fonts.AddFont(“OpenSans-Semibold.ttf”,
“OpenSansSemibold”); })
.ConfigureMauiHandlers((handlers) => {
#if Windows handlers.AddHandler(typeof(MyEntry),
typeof(MyMauiProject.Windows.Renderers. MyEntryRenderer));
#elif IOS......
#endif
});
return builder.Build();
}
}
C#
Note that their scope is global. This means that if we use and modify one handler for a
control—let’s say Button—this customization will affect all buttons.
.NET MAUI handlers are accessed through their control-specific interface, such as IButton
for a Button. This avoids the c ross-platform control having to reference its handler, and
the handler having to reference the cross-platform control. Clean architecture, right?
• PlatformView – Each handler class exposes the native view for the cross-platform
control via its PlatformView property. This property can be accessed to set native view
properties, invoke native view methods and subscribe to native view events.
• A property mapper defines what Actions to take when a property change occurs
in the cross-platform control. It’s a Dictionary that maps the cross-platform control’s
properties to their associated Actions. Each platform handler then provides
implementations of the Actions, which manipulate the native view API. This ensures
that when a property is set on a cross-platform control, the underlying native view is
updated as required.
• A command mapper defines what Actions to take when the cross-platform control
sends commands to native views.
So, handlers and mappers are great, but how do we use them? For example, how can we
port our code and modify the color of Entry component? Here are three ways.
This approach is not very difficult, and it is just one of the major scenarios to use handlers.
To use this approach, simply add the “Handler” keyword to the component you need to
modify (for example, in the constructor of our content page) and you will be good to use it.
When you want to customize the entry, you will need EntryHandler—for a button,
ButtonHandler, etc.
Ex: Microsoft.Maui.Handlers.EntryHandler
Then set the right mapping and use the PlatformView to access the native control.
(MyCustomization is a sample key name that we put in our mapping.)
void ModifyEntry()
{
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(“**MyCus
tomization**”, (handler, view) =>
{
#if WINDOWS
if (view is MyEntry) //here we check
and customize only MyEntry instances and not all entries, without
this we can easily customize all entries if we needed it
{
handler.
PlatformView.Background = Brush.Cyan;
}
#endif
});
}
C#
Handlers have their lifecycles and set of events that we can listen to. For example, we can
subscribe to the Entry instance and listen for HandlerChanged and HandlerChanging and
change the properties that we need there.
A complete example can be found in Microsoft docs .NET MAUI control customization with
handlers - .NET MAUI | Microsoft Learn and in Telerik docs showing this approach with
RadListView.
Conclusion
Handlers are so flexible, they bring performance improvements and their API is more
extensible. It needs time to get used to the concept, but it is worth it and is one of the
major reasons that make .NET MAUI better than Xamarin.Forms. So, go ahead and play
with this. You can also consider reading these Telerik and Microsoft resources for more
scenarios.
After that, you will still have to implement a good number of manual changes, such as
updating any third-party libraries and API changes.
This is also true when replacing Telerik UI for Xamarin with Telerik UI for .NET MAUI.
Do a mass replace from Telerik.XamarinForms.* to Telerik.MAUI.Controls or just use the
XAML scheme: xmlns:telerik=”http://schemas.telerik.com/2022/xaml/maui.
For more changes in the Telerik API, you can follow the articles below for Xamarin-to-MAUI
migration guides for Telerik UI controls:
• Common migration
• Accordion
• AutoComplete
• CheckBox
• ComboBox
• DataForm
• DatePicker
• DateTimePicker
• Entry
• ImageEditor
• ListPicker
• ListView
• MaskedEntry
• ProgressBar
• SignaturePad
• TemplatedPicker
• TimePicker
• TimeSpanPicker
Microsoft.Azure.Mobile.Client Microsoft.Datasync.Client
Microsoft.Azure.Mobile.Client.SqlLiteStore Microsoft.Datasync.Client.SQLLiteStor
There are also a lot of API changes, so be sure to read the MS docs before using them.
Refer to this MS doc for the detailed use cases: Device information - .NET MAUI | Microsoft
Learn.
if (Device.Idiom == TargetIdiom.Phone)
{
C#
if (DeviceInfo.Idiom == DeviceIdiom.Phone)
{
C#
That is why although .NET MAUI ListView has a lot of features and it is completely
possible to use it in the same way as in Xamarin, it is recommended to consider its
replacement with CollectionView.
In .NET MAUI, this functionality has been separated into the Microsoft.Maui.Graphics.Color
class and the Microsoft.Maui.Graphics.Colors class. So to find the AliceBlue in MAUI, you
can use the Colors class which defines 148 public static read-only fields for common colors.
Read more: Converters - .NET MAUI Community Toolkit - .NET Community Toolkit |
Microsoft Learn.
Grid Columns and rows Columns and rows Add ColumnDefinitions and RowDefinitions.
can be inferred must be explicitly
from XAML. declared.
RelativeLayout Requires the Use Grid instead or add the xmlns for the
compatibility compatibility namespace.
namespace.
StackLayout Children can hildren are stacked If you need child views to fill space, change to
fill space in the and will go beyond a Grid. You can also use VerticalStackLayout
stacking direction. available space. andHorizontalStackLayot instead.
These are just the major changes that you will face when migrating your Xamarin.Forms
app to .NET MAUI—but remember, rewriting and improving code cannot come without
such changes, and they are a result of new and better functionality that .NET MAUI brings
to the table.
Let’s say you have a great WPF app, perhaps your main target users are those using
Windows OS. However, the usage of Android, iOS and macOS devices continues to
increase and they are now a very important part of our ecosystem.
For reference, we can take a look at the data in Wikipedia: Usage share of operating
systems - Wikipedia.
Until recently, to reach all these users was not easy—you would write four different apps
if you needed to rely on a native look and feel for the user experience or to choose the
web stack and access the users via browsers. Let’s be honest, all of these options required
learning different technologies and going outside the .NET world.
But now, the .NET family is so big, and we can use it to extend and modernize our desktop
application to reach the sky (or, in other words, Linux, iOS, macOS and Android).
How? Let’s take a look at the most modern children in the family—.NET MAUI and .NET
Blazor. Both are a great choice to consider when thinking how to bring our desktop app to
new territories, but which one is right for you? Let’s take a quick test!
Is the native No, I want my UI to look Do you love XAML? No, I prefer CSS +HTML
look & feel important? the same everywhere
So, if the result led you to using .NET MAUI, scroll to the next heading. If the results led
you to using a Blazor Hybrid app, this is a great option too and we will look into it further
down this chapter.
XAML is a great invention and I personally like it a lot. However, there is no XAML
standard, which makes things complicated when we are talking about unification and
migration.
With .NET MAUI, we can leverage our XAML and C# skillset and bring our Windows
desktop app to more devices by moving it piece by piece.
Using Text
Here the well-known Label still exists, but not the TextBox component. In .NET MAUI, we
use Entry for short text and the Editor component for multiple lines. Telerik RadEntry is
also a great component when we are talking about text with some features that you may
need, such as built-in Validation.
Using Borders
In WPF, we can rely on the Height and Width properties of the FrameWorkElement
class, while in .NET MAUI the framework offers us HeightRequest and WidthRequest
instead, which are properties of the VisualElement class. These properties will call the
GetSizeRequest, which will in turn modify the final size the element receives during a
layout cycle.
The base layouts in .NET MAUI are also different from WPF, and I suggest you take a look
at the .NET MAUI documentation before porting the code directly: Layouts - .NET MAUI |
Microsoft Learn.
Note that every .NET Multi-platform App UI control that derives from View (this includes
views and layouts) has HorizontalOptions and VerticalOptions properties, of type
LayoutOptions, and these are your new best friends when positioning the elements.
<HorizontalStackLayout HorizontalOptions=”Center”
Margin=”0, 20, 0, 20”>
<Label Text=”Searching... “
FontSize=”16”
TextColor=”#8E8E93”/>
</HorizontalStackLayout/>
XML
I am listing here the common alternatives to the most used layouts from WPF:
Canvas X
StackPanel, VerticalStackPanel,
StackPanel HorizontalStackPanel
The ScrollViewer component is also not available, but you can rely on ScrollView to achieve
scrolling functionality. Read more about its API in the documentation: ScrollView - .NET
MAUI | Microsoft Learn.
.NET MAUI is a successor of the mobile Xamarin framework where windows are not
very used. That is why, by default, the base class of the XAML pages is not Window, but
ContentPage. ContentPages are used to achieve the navigation in a .NET MAUI app,
so the root window of the app uses them to change its content. When you migrate WPF
pages, change the base class to ContentPage.
Also, there are some “tricky” moments when we want to manipulate the window. For
example, to change its size. Here is a simple code sample for how to do that in App.xaml:
public App()
{
InitializeComponent();
Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMappin
g(nameof(IWindow), (handler, view) =>
{
#if WINDOWS
handler.PlatformView.Activate();
appWindow.Resize(new SizeInt32(WindowWidth,
WindowHeight));
#endif
});
MainPage = new AppShell();
}
}
C#
C#
With .NET 7, we can use multiple windows. This can be achieved by creating a Window
object and opening it using the OpenWindow method on the Application object.
C#
Note that multi-window support works on Android and Windows without additional
configuration. However, additional configuration is required on iPadOS and Mac Catalyst.
Read more about how to set it up in the Microsoft documentation here: .NET MAUI
windows - .NET MAUI | Microsoft Learn.
Events
The naming convention for events is also a little bit different. But basically adding “ed” to
the existing WPF events should do the trick.
Another interesting thing to point out is the key events. They are not exposed directly.
However, most of the UI components have their events that fire when the focus is lost or
the text is changed, and you can subscribe to them to do your job.
MyEntry.Completed += MyEntry_Completed;
C#
Another way is to access the native windows component and attach the event.
To do that, you can obtain the UIElement on which the key-press events should be
detected from Handler.PlatformView. And then you can hook up the native events.
C#
This is one of the great features of .NET MAUI—a common shared folder where you can
put the images, use the MAUIImage build action and directly access them in the code
without worrying about where exactly they are.
For example, if you place add.png to the image folder, you can access it from a button by
its short name:
Another important thing that you should know is how to customize UI or behavior per
platform. You can use two major approaches:
C#
For more information, see .NET MAUI invoking platform code - .NET MAUI | Microsoft
Learn.
<ContentPage xmlns=”http://schemas.microsoft.com/dotnet/2021/
maui” xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml”
x:Class=”...”>
<ContentPage.Padding>
<OnPlatform x:TypeArguments=”Thickness”>
<On Platform=”iOS, Android” Value=”10, 20, 20, 10” />
</OnPlatform>
</ContentPage.Padding>
</ContentPage>
XML
Accessibility
Another very important topic for modern apps is accessibility. In WPF, we have a lot of tools to achieve
that. One of them is the AutomationPeer class. In .NET MAUI, we will use semantic properties to make
our app accessible. Read more about semantic properties here: Build accessible apps with semantic
properties - .NET MAUI | Microsoft Learn.
• The first case for using such an approach is if we want our app to have a unified UI,
to write the code at once but we need all desktop features, like file access system,
camera settings, etc.
• Another situation is when we have already ported our code to .NET MAUI but need
a component that the Blazor ecosystem has to offer, such as Telerik Pivot or Telerik
ScheduleView, for example, or another of the powerful components from Telerik UI for
Blazor.
Scenario 1
Unified UI
The best choice here is to create a new Hybrid Blazor app using Microsoft VS
Templates.
With .NET 7, you can choose between WPF Hybrid Blazor or .NET MAUI Blazor, and which
one to choose depends which OS you need to target.
Visual Studio directly creates a Blazor app wrapped in the .NET MAUI project structure.
Scenario 2
We have a great MAUI/WPF app but we need a component that only the Blazor
ecosystem has to offer.
For example, if you need to use Scheduling functionality in .NET MAUI, then you can look
into the rich Telerik UI for Blazor suite.
In this case, our .NET MAUI app is already created and we need to follow the steps below
to add the Blazor part or you can again create a blank MAUI Hybrid app and copy the
needed files from there.
1. Add the Razor SDK, Microsoft.NET.Sdk.Razor to your project by editing its first line
of the CSPROJ project file:
<Project Sdk=”Microsoft.NET.Sdk.Razor”>
Razor C#
2. Add the root Razor component for the app to the project Main.razor page:
A razor component is a page containing the UI for your needs. It is the place to write your
code when working with Blazor.
For example, the code that I will use to add the Scheduler is placed in the Pages folder:
@Page “/”
@Using Telerik.Blazor.Components.Scheduler.Models;
<Telerikscheduler Data=”@Appointments” @Bind-Date=”@Startdate”
Height=”600px” @Bind-View=”@Currview”
Allowcreate=”True” Allowdelete=”True”
Allowupdate=”True”
Confirmdelete=”True”
>
<Schedulerviews>
<Schedulerdayview Starttime=”@Daystart” Endtime=”@Dayend”
Workdaystart=”@Workdaystart” Workdayend=”@Workdayend” />
<Schedulerweekview Starttime=”@Daystart” Endtime=”@Dayend”
Workdaystart=”@Workdaystart” Workdayend=”@Workdayend” />
<Schedulermultidayview Starttime=”@Daystart” Endtime=”@
Dayend” Workdaystart=”@Workdaystart” Workdayend=”@Workdayend”
Numberofdays=”10” />
<Schedulermonthview></Schedulermonthview>
<Schedulertimelineview Starttime=”@Daystart” Endtime=”@
Dayend” Workdaystart=”@Workdaystart” Workdayend=”@Workdayend” />
</Schedulerviews>
</Telerikscheduler>
@code {
IEnumerable<Appointment> Appointments = new
List<Appointment>();
public DateTime StartDate { get; set; } = new DateTime(2021, 6,
21);
public SchedulerView CurrView { get; set; } = SchedulerView.
Week;
Razor C#
5. Add any optional _Imports.razor files to your project. This means list here the
additional libraries that you will use.
Here, to use Telerik UI for Blazor, the following code should be added:
@using Telerik.Blazor
@using Telerik.Blazor.Components
@using Telerik.FontIcons
@using Telerik.SvgIcons
<ContentPage xmlns=”http://schemas.microsoft.com/dotnet/2021/maui”
xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml”
xmlns:local=”clr-namespace:MyBlazorApp”
x:Class=”MyBlazorApp.MainPage”>
<BlazorWebView HostPage=”wwwroot/index.html”>
<BlazorWebView.RootComponents>
<RootComponent Selector=”#app” ComponentType=”{x:Type
local:Main}” />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>
Razor C#
builder.Services.AddMauiBlazorWebView();
#if DEBUG
builder.Services.AddMauiBlazorWebViewDeveloperTools();
#endif
// Register any app services on the IServiceCollection
object
// e.g. builder.Services.AddSingleton<WeatherForecastServi
ce>();
return builder.Build();
}
}
C#
And when the BlazorWebView is added and your .NET MAUI app becomes a .NET MAUI
Blazor Hybrid app, it is time to add Telerik ScheduleView. The steps to do that are:
7. Add Telerik libraries by following the link: Download Telerik UI for Blazor
8. Add the Telerik client assets by adding these two lines in the <head> tag of
wwroot/index.html:
HTML
@using Telerik.Blazor
@using Telerik.Blazor.Components
@using Telerik.FontIcons
@using Telerik.SvgIcons
Razor C#
<TelerikRootComponent>
<Router AppAssembly=”@typeof(Main).Assembly”>
<Found Context=”routeData”>
<RouteView RouteData=”@routeData” DefaultLayout=”@
typeof(MainLayout)” />
<FocusOnNavigate RouteData=”@routeData” Selector=”h1”
/>
</Found>
<NotFound>
<LayoutView Layout=”@typeof(MainLayout)”>
<p role=”alert”>Sorry, there’s nothing at this
address.</p>
</LayoutView>
</NotFound>
</Router>
</TelerikRootComponent>
Razor C#
11. Register the Telerik Services by modifying once the CreateMauiApp() method:
Razor C#
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”300” />
<ColumnDefinition Width=”*” />
</Grid.ColumnDefinitions>
<ProgressBar
x:Name=”isRefreshingControl”
/>
<ListView
x:Name=”itemListControl”
Grid.Row=”1”
Margin=”10”
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<HorizontalStackLayout
HorizontalOptions=”Center” VerticalOptions=”Center” >
<CheckBox Margin=”1” Color=”Black”
/>
<Label Text=”{Binding}”
VerticalOptions=”Center”/>
</HorizontalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
…........
<BlazorWebView Grid.Column=”1” Grid.RowSpan=”3”
x:Name=”blazorWebView” HostPage=”wwwroot/index.html”>
<BlazorWebView.RootComponents>
<RootComponent Selector=”#app”
ComponentType=”{x:Type local:Main}” />
</BlazorWebView.RootComponents>
</BlazorWebView>
</Grid>
</ContentPage>
XML
Telerik UI for .NET MAUI library delivers 60+ components that will
accelerate your cross-platform application development and help you
modernize legacy projects.
Rossitsa Fakalieva was the leader of the Telerik engineering teams working with
XAML technologies—Telerik UI for WPF, Telerik UI for Xamarin and Telerik UI for
.NET MAUI—for over a decade. She’s now dedicated to empowering women to
success in IT through her organizations, Women Who Code – Sofia and Coding
with Rossi.
Learn More