7 Tips to Boost .NET MAUI Mobile App Performance

In this blog post, we'll share seven tips to help you create high-speed .NET MAUI applications and deliver user experiences that amaze. The following tips will leverage standard .NET MAUI options alongside capabilities included in our .NET MAUI product line.

1. Test Your Project in Release Configuration

While switching from the Debug to Release configuration may not be that noticeable in desktop projects (WinFroms, WPF), this option offers huge performance benefits in .NET MAUI applications.

Switching to Release Configuration in Visual Studio

Changing configuration achieves three main things:

  1. The Linker starts using the trimming mechanism to reduce the size of deployed assemblies. The Linker inspects source code and removes all unused branches from the assemblies. You can learn more about trimming in the following article: Trim self-contained deployments and executables.
  2. The compiler performs optimizations when generating intermediate language (IL) code.
  3. Visual Studio Debugger is detached, which means you won’t see any logs in the Output window during app execution. Detaching the debugger helps reduce costs produced through communication between the app and tracing mechanism.

2. Use DXCollectionView Instead of Standard CollectionView

Although both collection views use virtualization mechanisms, DXCollectionView includes additional optimizations to maintain excellent scrolling speed even when you use complex item templates.

One of the optimizations is called Cascade Updates. When users rapidly scroll DXCollectionView, they often don't have sufficient time to read each item as it appears on screen. DXCollectionView uses this reality and doesn’t draw all items simultaneously: it loads them one by one and plays an animation as data is retrieved. This feature is extremely helpful if you need to display complex content for DXCollectionView items. The following animation demonstrates the difference in scrolling speed between the standard CollectionView and DevExpress DXCollectionView.

In usage scenarios with simpler item templates, you may disable Cascade Updates via the AllowCascadeUpdate property - scrolling experience should remain perfect.

GitHub Example: Replicate a Single-Column Kanban View

Our recent release (v23.1), includes new scrolling optimizations for the DXCollectionView and Data Grid. The optimization rate varies depending on target device, settings and other factors. We achieved the most significant results in the Data Grid on iOS, where vertical scrolling is up to 70% faster than previous versions. Therefore, if you are using v22.2 or older, you can consider updating to v23.1 to speed up scroll operations.

3. Call DevExpress Initializers on Application Startup

When an application shows a control for the first time, .NET MAUI loads assemblies, parses XAML resources, and calls static constructors. These operations may cause a noticeable delay when users navigate from one view to another. DevExpress components give you a way to enable/execute all initialization steps when the application is being loaded. To do this, simply call Initializer.Init in the CreateMauiApp method:


public static MauiApp CreateMauiApp() { 
  var builder = MauiApp.CreateBuilder(); 
  builder 
    .UseMauiApp() 
    .UseDevExpress(); 
  DevExpress.Maui.Charts.Initializer.Init(); 
  DevExpress.Maui.CollectionView.Initializer.Init(); 
  DevExpress.Maui.Controls.Initializer.Init(); 
  DevExpress.Maui.Editors.Initializer.Init(); 
  DevExpress.Maui.DataGrid.Initializer.Init(); 
  DevExpress.Maui.Scheduler.Initializer.Init(); 
  return builder.Build(); 

According to our tests, moving initialization to the CreateMauiApp method doesn’t materially affect application startup, but significantly decreases view switching time.

MAUI Startup Optimization DevExpress

4. Follow Standard Mobile UI Patterns to Simplify Layouts

This section is especially important if previously worked on a desktop application. Mobile applications rarely require sophisticated interfaces and it might be challenging to rethink the user flow to eliminate desktop UI patterns. Doing so, however, will help you achieve better performance and overall user experience.

In general, you don’t need to fit all information on one small mobile screen. This may confuse users and make touch interactions more difficult. A better option is to provide more space for UI elements and display additional information upon request.

One technique is to logically split information and user tasks across multiple pages. For example, if you are implementing CRUD operations in a list, you can create the following pages:

  • A main view with CollectionView with search and navigation.
  • A detail view to display more information about a clicked Item.
  • An editing view to allow users modify or create items.
MAUI CRUD DevExpress

GitHub Example: CollectionView for .NET MAUI - Incorporate CRUD Operations

Our DXCollectionView and Data Grid offer APIs to help you implement this flow. You can use default detail/editing views or specify custom pages. Once you do, DXCollectionView/DataGrid will automatically navigate to them as needed. BindingContext in these pages contain information and commands that may require custom logic.

Another technique is to display detail information on the same page - when a user selects an element. Our Bottom Sheet is a great choice for such a usage scenario.

MAUI BottomSheet DevExpress

GitHub Example: BottomSheet with Maps

GitHub Example: Master-Detail View with BottomSheet

5. Use the Shimmer Control for Data Loaded Asynchronously

When users switch a view, the application often starts loading data. You can maintain UI responsiveness during this process and display an element informing users about load operations. While you can use a simple activity indicator, it doesn’t give users an idea of the UI structure. You may find it more intuitive to use DevExpress ShimmerControl to help users understand where UI elements are located. This allows users to decide with what part of the UI they will be interacting once loading completes.

MAUI Shimmer (Skeleton) Control Loading MAUI Shimmer (Skeleton) Control Loaded

6. Load Large Data Sources on Demand

In large lists, users typically don't need to access all data records simultaneously. They usually need to view either the most relevant data items or items that meet a certain filter criterion.

The first technique implies the following flow:

  1. You sort your data items based on relevance (update date, item price etc.),
  2. You load a small initial portion of data.
  3. You load more items when a user scrolls to the end of the screen.

The simplest way to implement this flow is to use Infinite Scrolling available in DXCollectionView and Data Grid:

MAUI Infinite Scrolling (Load More)

To achieve this, simply set IsLoadMoreEnabled to true and handle the LoadMore event or LoadMoreCommand command:


<dxcv:DXCollectionView IsRefreshing="{Binding IsLoading, Mode=TwoWay}" 
						  IsLoadMoreEnabled="True" 
                          LoadMoreCommand="{Binding LoadMoreCommand}">
    <!--...-->
</dxcv:DXCollectionView>

public class MainViewModel {
    public ICommand LoadMoreCommand { get; set; }
    public MainViewModel() {
        //... 
        LoadMoreCommand = new Command(LoadMore, CanLoadMore);
    }
    public void LoadMore() {
        //Load data from a service
    }
}

GitHub Example: CollectionView for .NET MAUI - Infinite Scrolling

Another usage scenario is accessing records based on search text, item values and other filter conditions. You can request rows from the database based on a user filter to minimize the amount of loaded records. For example, if you are using Entity Framework, you can incorporate a user filter into a LINQ expression. Please refer to the following Microsoft help topic for additional information: Expressions in LINQ to Entities Queries

7. Use DataType to Enable Compiled Bindings

As you may know, default .NET MAUI bindings use Reflection the access properties by their names. This isn’t cost-effective and may affect views with many bindings.

.NET MAUI offers a mechanism that allows you to resolve bindings at compile time. It’s sufficient to set the x:DataType attribute to the type of object stored in BindingContext. For example, if you bound DXCollectionView to a collection of contacts, ItemTemplate will contain an instance of the Contact class in its BindingContext. Therefore, you need to set x:DataType to “model:Contact” where “model” is the namespace where the Contact class is defined:


<dxcv:DXCollectionView.ItemTemplate> 
    <DataTemplate x:DataType="model:Contact"> 
        <Label Text="{Binding FirstName}"/> 
    </DataTemplate> 
</dxcv:DXCollectionView.ItemTemplate> 

Let's take a brief look at how compiled bindings compare to classic bindings:

  • Bindings with property change notifications are resolved eight times faster
  • Bindings without property-change notifications (i.e. OneTime bindings) are resolved approximately twenty times faster
  • Setting BindingContext on a binding with property change notifications is approximately five times faster
  • Setting BindingContext on a binding without property change notifications is approximately seven times faster

Please refer to the following Microsoft help topic to learn more: Compiled bindings.

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.