Md Mominul Islam | Software and Data Enginnering | SQL Server, .NET, Power BI, Azure Blog

while(!(succeed=try()));

LinkedIn Portfolio Banner

Latest

Home Top Ad

Responsive Ads Here

Post Top Ad

Responsive Ads Here

Wednesday, September 3, 2025

.NET MAUI Cross-Platform App Development in 2025

 

Introduction to .NET MAUI: Your Gateway to Cross-Platform Development

In 2025, the demand for apps that work seamlessly across iOS, Android, macOS, and Windows continues to grow. Developers need efficient tools to deliver native-like experiences without duplicating codebases. Enter .NET MAUI (Multi-platform App UI), Microsoft’s powerful framework for building native, cross-platform applications using a single C# and XAML codebase. Evolving from Xamarin.Forms, .NET MAUI simplifies development, boosts performance, and supports modern app requirements.

This comprehensive guide is designed for beginners and advanced developers alike. We’ll walk you through building real-world apps, from basic to advanced scenarios, with practical examples. You’ll also discover best practices, pros and cons, and alternatives to make informed decisions for your projects. Whether you’re creating a personal finance tracker or an enterprise-grade app, this guide has you covered.


Module 1: What is .NET MAUI and Why Use It?

Understanding .NET MAUI

.NET MAUI is an open-source framework that allows developers to create native apps for iOS, Android, macOS, and Windows from a single codebase. Built on .NET 8, it uses C# and XAML to deliver native performance and UI, with access to platform-specific APIs when needed. Unlike Xamarin.Forms, .NET MAUI extends to desktop platforms and introduces features like hot reload and a unified project structure.

Why Choose .NET MAUI in 2025?

  • Single Codebase: Write once, deploy to multiple platforms, reducing development time.

  • Native Performance: Compiles to native code (AOT for iOS, JIT for Android).

  • Rich Ecosystem: Leverages .NET libraries, Visual Studio, and third-party controls.

  • Hot Reload: Update UI and code in real-time without restarting the app.

  • Community Support: Active communities on GitHub, Stack Overflow, and Microsoft Q&A.

Pros and Cons

Pros:

  • Unified project structure simplifies maintenance.

  • Native UI rendering for a polished, platform-specific look.

  • Extensive APIs for device features (e.g., GPS, sensors).

  • Seamless integration with Visual Studio 2022.

  • Strong Microsoft backing and open-source community.

Cons:

  • Still maturing, with some controls (e.g., maps) incomplete as of 2025.

  • Learning curve for developers new to C# or XAML.

  • Occasional platform-specific quirks require workarounds.

  • Smaller community compared to Flutter or React Native.

Alternatives

  • Flutter: Uses Dart for cross-platform apps, with a rich widget library and strong community.

  • React Native: JavaScript-based, ideal for web developers, with extensive third-party plugins.

  • Kotlin Multiplatform: Emerging framework for sharing logic across platforms, best for Kotlin experts.

  • Uno Platform: A .NET-based alternative with broader platform support, including web.


Module 2: Setting Up Your .NET MAUI Development Environment

Prerequisites

  • IDE: Visual Studio 2022 (Community, Professional, or Enterprise) on Windows or macOS. For Linux, use Visual Studio Code with the .NET MAUI extension.

  • .NET SDK: Version 8.0 or later.

  • Platform SDKs:

    • Android: Android SDK (API 21+).

    • iOS/macOS: Xcode 16+ (macOS only for iOS development).

    • Windows: Windows 10/11 SDK.

  • Hardware: A Mac is required for iOS/macOS builds, even from Windows (via remote Mac).

Step-by-Step Setup

  1. Install Visual Studio 2022:

    • Download from visualstudio.microsoft.com.

    • Select the “.NET Multi-platform App UI development” workload during installation.

  2. Install .NET SDK:

    • Run dotnet --version in a terminal to verify .NET 8.0+ is installed.

  3. Configure Emulators/Simulators:

    • Android: Set up an Android emulator via Visual Studio’s Device Manager.

    • iOS: Configure an iOS simulator in Xcode (macOS only).

    • Windows/macOS: Use local machine or virtual machines for testing.

  4. Verify Setup:

    • Create a new .NET MAUI project in Visual Studio to ensure all dependencies are installed.

Example: Creating Your First .NET MAUI Project

Let’s create a simple “Hello, World!” app to verify your setup.

  1. Open Visual Studio 2022.

  2. Select Create a new project > .NET MAUI App > Name it HelloMauiApp.

  3. Choose .NET 8.0 in the framework dropdown and create the project.

  4. Open MainPage.xaml and replace its content with:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloMauiApp.MainPage">
    <VerticalStackLayout>
        <Label Text="Welcome to .NET MAUI!"
               FontSize="24"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />
        <Button Text="Click Me"
                Clicked="OnButtonClicked"
                HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>
  1. Open MainPage.xaml.cs and add:

namespace HelloMauiApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnButtonClicked(object sender, EventArgs e)
    {
        await DisplayAlert("Hello!", "You clicked the button!", "OK");
    }
}
  1. Set the debug target (e.g., Android Emulator, iOS Simulator, or Windows Machine) and press F5 to run.

This app displays a welcome message and a button that triggers an alert when clicked. Test it on multiple platforms to ensure compatibility.


Module 3: Core Concepts of .NET MAUI

Single Project Structure

.NET MAUI uses a single project to target all platforms, unlike Xamarin’s separate projects per platform. Key components:

  • Platforms Folder: Contains platform-specific code (e.g., Android, iOS).

  • Resources Folder: Shared assets like images, fonts, and styles.

  • App.xaml: Defines app-wide resources and styles.

  • MauiProgram.cs: Configures the app’s entry point and services.

XAML vs. C# for UI

You can define UI using XAML (declarative) or C# (programmatic). XAML is preferred for its readability and designer support.

Data Binding and MVVM

.NET MAUI supports the Model-View-ViewModel (MVVM) pattern for clean separation of concerns. Data binding connects UI elements to data sources, reducing boilerplate code.

Example: Building a Task List App with MVVM

Let’s create a task list app where users can add and view tasks, demonstrating MVVM and data binding.

  1. Model: Define a TaskItem class in Models/TaskItem.cs:

namespace TaskListApp.Models;

public class TaskItem
{
    public string Name { get; set; }
    public bool IsCompleted { get; set; }
}
  1. ViewModel: Create TaskViewModel.cs in a ViewModels folder:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace TaskListApp.ViewModels;

public class TaskViewModel : INotifyPropertyChanged
{
    private string _newTaskName;
    public ObservableCollection<TaskItem> Tasks { get; } = new ObservableCollection<TaskItem>();

    public string NewTaskName
    {
        get => _newTaskName;
        set
        {
            _newTaskName = value;
            OnPropertyChanged(nameof(NewTaskName));
        }
    }

    public ICommand AddTaskCommand { get; }

    public TaskViewModel()
    {
        AddTaskCommand = new Command(AddTask, () => !string.IsNullOrEmpty(NewTaskName));
    }

    private void AddTask()
    {
        Tasks.Add(new TaskItem { Name = NewTaskName, IsCompleted = false });
        NewTaskName = string.Empty;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. View: Update MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TaskListApp.MainPage">
    <VerticalStackLayout Padding="20">
        <Entry Text="{Binding NewTaskName}"
               Placeholder="Enter task name" />
        <Button Text="Add Task"
                Command="{Binding AddTaskCommand}" />
        <CollectionView ItemsSource="{Binding Tasks}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <HorizontalStackLayout>
                        <CheckBox IsChecked="{Binding IsCompleted}" />
                        <Label Text="{Binding Name}" />
                    </HorizontalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>
  1. Wire Up ViewModel: In MainPage.xaml.cs:

namespace TaskListApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = new ViewModels.TaskViewModel();
    }
}

This app lets users add tasks and mark them as completed, with the UI updating automatically via data binding. The MVVM pattern keeps the code organized and testable.


Module 4: Advanced Scenarios

Scenario 1: Personal Finance Tracker

Let’s build a finance tracker app with charts to visualize income and expenses, using Syncfusion’s .NET MAUI controls for advanced UI components.

  1. Install Syncfusion.Maui.Charts:

    • Add the Syncfusion.Maui.Charts NuGet package to your project.

  2. Model: Create Transaction.cs:

namespace FinanceTracker.Models;

public class Transaction
{
    public string Category { get; set; }
    public double Amount { get; set; }
    public DateTime Date { get; set; }
}
  1. ViewModel: Create FinanceViewModel.cs:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace FinanceTracker.ViewModels;

public class FinanceViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Transaction> Transactions { get; } = new ObservableCollection<Transaction>
    {
        new Transaction { Category = "Salary", Amount = 3000, Date = DateTime.Now.AddDays(-10) },
        new Transaction { Category = "Rent", Amount = -1200, Date = DateTime.Now.AddDays(-5) },
        new Transaction { Category = "Groceries", Amount = -200, Date = DateTime.Now }
    };

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. View: Update MainPage.xaml with a Syncfusion chart:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sf="clr-namespace:Syncfusion.Maui.Charts;assembly=Syncfusion.Maui.Charts"
             x:Class="FinanceTracker.MainPage">
    <VerticalStackLayout Padding="20">
        <sf:SfCartesianChart Title="Monthly Transactions">
            <sf:SfCartesianChart.XAxes>
                <sf:DateTimeAxis />
            </sf:SfCartesianChart.XAxes>
            <sf:SfCartesianChart.YAxes>
                <sf:NumericalAxis />
            </sf:SfCartesianChart.YAxes>
            <sf:ColumnSeries ItemsSource="{Binding Transactions}"
                             XBindingPath="Date"
                             YBindingPath="Amount" />
        </sf:SfCartesianChart>
    </VerticalStackLayout>
</ContentPage>
  1. Wire Up ViewModel: In MainPage.xaml.cs:

namespace FinanceTracker;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = new ViewModels.FinanceViewModel();
    }
}

This app displays a column chart of transactions, with positive amounts (income) and negative amounts (expenses). Syncfusion’s controls enhance the UI with professional-grade visuals.

Scenario 2: Platform-Specific Features

Sometimes, you need platform-specific behavior (e.g., a toast on Android or an alert on iOS). Use conditional compilation:

public async Task ShowMessage(string message)
{
#if ANDROID
    Android.Widget.Toast.MakeText(Android.App.Application.Context, message, Android.Widget.ToastLength.Short).Show();
#elif IOS
    var alert = new UIKit.UIAlertController
    {
        Title = "Message",
        Message = message
    };
    alert.AddAction(UIKit.UIAlertAction.Create("OK", UIKit.UIAlertActionStyle.Default, null));
    await MainThread.InvokeOnMainThreadAsync(() => 
        UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null));
#endif
}

Call this method from a ViewModel to show platform-specific notifications.


Module 5: Best Practices and Standards

Best Practices

  1. Use MVVM: Separate business logic (ViewModel) from UI (View) for maintainability.

  2. Optimize Performance:

    • Use asynchronous methods (async/await) for network or file operations.

    • Minimize UI updates by batching changes in ViewModels.

  3. Leverage Native Controls: Use .NET MAUI’s native rendering for platform-specific look and feel.

  4. Resource Management: Store shared assets (images, fonts) in the Resources folder and use platform-specific scaling.

  5. Testing: Test on emulators, simulators, and physical devices for each platform.

  6. Hot Reload: Use XAML and C# hot reload to speed up UI development.

  7. Third-Party Controls: Use libraries like Syncfusion, Telerik, or DevExpress for advanced UI components.

Standards

  • Code Style: Follow C# coding conventions (e.g., PascalCase for public members).

  • Accessibility: Use SemanticProperties in XAML to support screen readers.

  • Versioning: Specify app version in the MauiApp.csproj manifest.

  • Dependency Injection: Use MauiProgram.cs to register services for cleaner code.


Module 6: Deployment and Testing

Testing

  • Emulators/Simulators: Use Android Emulator, iOS Simulator, and local machines for initial testing.

  • Physical Devices: Test on real devices to catch platform-specific issues.

  • Unit Testing: Use xUnit or NUnit for ViewModel tests.

  • UI Testing: Use Appium or Xamarin.UITest for automated UI tests.

Deployment

  1. Android:

    • Generate an .apk or .aab file in Visual Studio.

    • Publish to Google Play Store following their guidelines.

  2. iOS:

    • Use a Mac to build an .ipa file.

    • Submit to the App Store via Xcode or Transporter.

  3. Windows/macOS:

    • Package as MSIX (Windows) or .app (macOS).

    • Distribute via Microsoft Store or direct downloads.

Example: Publishing to Android

  1. In Visual Studio, set the project to Release mode.

  2. Right-click the project > Publish > Android.

  3. Follow the wizard to generate an .aab file and upload it to Google Play Console.


Module 7: Real-World Case Study

Building a Fitness Tracker App

Let’s outline a fitness tracker app that logs workouts and uses device sensors (e.g., accelerometer) for step counting.

  1. Model: Create Workout.cs:

namespace FitnessTracker.Models;

public class Workout
{
    public string Name { get; set; }
    public int DurationMinutes { get; set; }
    public DateTime Date { get; set; }
}
  1. ViewModel: Create WorkoutViewModel.cs:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace FitnessTracker.ViewModels;

public class WorkoutViewModel : INotifyPropertyChanged
{
    private string _workoutName;
    private int _duration;

    public ObservableCollection<Workout> Workouts { get; } = new ObservableCollection<Workout>();

    public string WorkoutName
    {
        get => _workoutName;
        set
        {
            _workoutName = value;
            OnPropertyChanged(nameof(WorkoutName));
        }
    }

    public int Duration
    {
        get => _duration;
        set
        {
            _duration = value;
            OnPropertyChanged(nameof(Duration));
        }
    }

    public ICommand AddWorkoutCommand { get; }

    public WorkoutViewModel()
    {
        AddWorkoutCommand = new Command(AddWorkout, () => !string.IsNullOrEmpty(WorkoutName) && Duration > 0);
    }

    private void AddWorkout()
    {
        Workouts.Add(new Workout
        {
            Name = WorkoutName,
            DurationMinutes = Duration,
            Date = DateTime.Now
        });
        WorkoutName = string.Empty;
        Duration = 0;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. View: Update MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FitnessTracker.MainPage">
    <VerticalStackLayout Padding="20">
        <Entry Text="{Binding WorkoutName}"
               Placeholder="Enter workout name" />
        <Entry Text="{Binding Duration}"
               Placeholder="Duration (minutes)"
               Keyboard="Numeric" />
        <Button Text="Add Workout"
                Command="{Binding AddWorkoutCommand}" />
        <CollectionView ItemsSource="{Binding Workouts}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <HorizontalStackLayout>
                        <Label Text="{Binding Name}" />
                        <Label Text="{Binding DurationMinutes, StringFormat=' ({0} min)'}"
                               HorizontalOptions="EndAndExpand" />
                    </HorizontalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>
  1. Access Accelerometer: Add a step counter using .NET MAUI’s sensor APIs:

using System.Numerics;

namespace FitnessTracker.Services;

public class StepCounterService
{
    private int _stepCount;

    public int StepCount
    {
        get => _stepCount;
        private set
        {
            _stepCount = value;
            OnStepCountChanged?.Invoke(value);
        }
    }

    public event Action<int> OnStepCountChanged;

    public void Start()
    {
        if (Accelerometer.IsSupported)
        {
            Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
            Accelerometer.Start(SensorSpeed.UI);
        }
    }

    private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
    {
        var data = e.Reading.Acceleration;
        if (Math.Abs(data.X) > 1.5 || Math.Abs(data.Y) > 1.5 || Math.Abs(data.Z) > 1.5)
        {
            StepCount++;
        }
    }

    public void Stop()
    {
        if (Accelerometer.IsSupported)
        {
            Accelerometer.Stop();
            Accelerometer.ReadingChanged -= Accelerometer_ReadingChanged;
        }
    }
}
  1. Integrate Service: Update MauiProgram.cs to register the service:

using Microsoft.Extensions.DependencyInjection;

namespace FitnessTracker;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .Services.AddSingleton<Services.StepCounterService>();

        return builder.Build();
    }
}

This app allows users to log workouts and track steps using the accelerometer, showcasing .NET MAUI’s ability to handle device features and complex UI.


Module 8: Comparing .NET MAUI with Alternatives

Feature

.NET MAUI

Flutter

React Native

Kotlin Multiplatform

Language

C#, XAML

Dart

JavaScript

Kotlin

Platforms

iOS, Android, macOS, Windows

iOS, Android, Web, Desktop

iOS, Android, Web

iOS, Android, Desktop, Web

Performance

Native (AOT/JIT)

Near-native (Skia)

Near-native (Bridge)

Native (via Kotlin/Native)

Community

Growing

Large

Large

Emerging

Learning Curve

Moderate (C# knowledge)

Moderate (Dart)

Low (JavaScript)

High (Kotlin expertise)

UI Framework

XAML, Native Controls

Widgets

Components

Compose Multiplatform

When to Choose .NET MAUI:

  • Your team is experienced in C# or .NET.

  • You need native performance and deep platform integration.

  • You’re building enterprise apps with complex business logic.

When to Choose Alternatives:

  • Flutter: For rapid prototyping and vibrant UI with a large community.

  • React Native: For web developers transitioning to mobile apps.

  • Kotlin Multiplatform: For Kotlin-based teams targeting logic sharing.


Conclusion

.NET MAUI is a game-changer for cross-platform development in 2025, offering a unified, high-performance framework for iOS, Android, macOS, and Windows. By following this guide, you’ve learned how to set up your environment, build real-world apps, and apply best practices. From simple task lists to advanced fitness trackers, .NET MAUI empowers developers to create robust, native apps with minimal effort.

No comments:

Post a Comment

Thanks for your valuable comment...........
Md. Mominul Islam

Post Bottom Ad

Responsive Ads Here