• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
Sas 101

Sas 101

Master the Art of Building Profitable Software

  • Home
  • Terms of Service (TOS)
  • Privacy Policy
  • About Us
  • Contact Us
  • Show Search
Hide Search

Build Stunning Cross-Platform Apps with .NET MAUI

UnknownX · February 1, 2026 · Leave a Comment

Building Production-Ready Cross-Platform Apps with .NET MAUI

 Executive Summary

.NET MAUI solves a critical problem in modern software development: the need to maintain separate codebases for iOS, Android, macOS, and Windows applications. As a .NET developer, you already possess the skills needed to build native mobile and desktop applications—MAUI eliminates the context-switching burden of learning platform-specific languages and frameworks.

This matters for production because it directly impacts time-to-market, maintenance costs, and code quality. A single shared codebase means bug fixes propagate across all platforms simultaneously, feature development accelerates, and your team stays focused on business logic rather than platform plumbing. For enterprise applications, this translates to reduced technical debt and faster iteration cycles.

## Prerequisites

Before starting, ensure your development environment is properly configured:

– **Visual Studio 2026** (or later) with the .NET MAUI workload installed
– **.NET 10.0 SDK** or later
– **Xcode** (latest version) for macOS/iOS development
– **Android SDK** with API level 21 or higher for Android development
– A working understanding of **C# 12+** and **XAML** markup
– Familiarity with **async/await patterns** and dependency injection

Verify your installation by running:

“`csharp
dotnet –version
dotnet workload list
“`

## Step-by-Step Implementation

### Step 1: Create Your First MAUI Project

Open Visual Studio 2026 and follow this workflow:

1. Click **Create a new project**
2. Search for “MAUI App” in the template search bar
3. Select the **.NET MAUI App** template and click **Next**
4. Enter your project name (e.g., `ProductionMauiApp`) and click **Next**
5. Select **.NET 10.0** in the Framework dropdown
6. Click **Create**

Visual Studio generates a single-project structure containing all platform-specific configurations, resources, and shared code. This unified approach is the foundation of MAUI’s power.

### Step 2: Understanding the Project Structure

Your newly created project contains:

“`
ProductionMauiApp/
├── Platforms/
│ ├── Android/
│ ├── iOS/
│ ├── MacCatalyst/
│ └── Windows/
├── Resources/
│ ├── AppIcon/
│ ├── Fonts/
│ ├── Images/
│ └── Styles/
├── App.xaml
├── App.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── MauiProgram.cs
└── ProductionMauiApp.csproj
“`

The **Platforms** folder contains platform-specific code that runs only on its target OS. The **Resources** folder centralizes all assets—images, fonts, and styles—managed in a single location rather than duplicated across platforms.

### Step 3: Configure Your Application Shell

The `MauiProgram.cs` file is your application’s composition root. This is where you configure services, register handlers, and initialize your app:

using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using ProductionMauiApp.Services;
using ProductionMauiApp.ViewModels;
using ProductionMauiApp.Views;

namespace ProductionMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        
        builder
            .UseMauiApp()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            // Register platform-specific services
            .ConfigureServices()
            // Configure custom handlers for native customization
            .ConfigureHandlers();

        return builder.Build();
    }

    private static MauiAppBuilder ConfigureServices(this MauiAppBuilder builder)
    {
        // Register your services with dependency injection
        builder.Services.AddSingleton<IProductService, ProductService>();
        builder.Services.AddSingleton<INavigationService, NavigationService>();
        builder.Services.AddSingleton();
        builder.Services.AddSingleton();

        return builder;
    }

    private static MauiAppBuilder ConfigureHandlers(this MauiAppBuilder builder)
    {
        #if ANDROID
        builder.ConfigureEffects(effects =>
        {
            // Android-specific handler customizations
        });
        #endif

        #if IOS
        builder.ConfigureEffects(effects =>
        {
            // iOS-specific handler customizations
        });
        #endif

        return builder;
    }
}

### Step 4: Build Your First Page with MVVM Architecture

Create a clean separation between UI and business logic using the Model-View-ViewModel pattern:

**ProductViewModel.cs:**

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

namespace ProductionMauiApp.ViewModels;

public class ProductViewModel : BaseViewModel
{
    private readonly IProductService _productService;
    private ObservableCollection _products;
    private bool _isLoading;
    private string _searchQuery;

    public ObservableCollection Products
    {
        get => _products;
        set => SetProperty(ref _products, value);
    }

    public bool IsLoading
    {
        get => _isLoading;
        set => SetProperty(ref _isLoading, value);
    }

    public string SearchQuery
    {
        get => _searchQuery;
        set
        {
            if (SetProperty(ref _searchQuery, value))
            {
                SearchCommand.Execute(null);
            }
        }
    }

    public ICommand LoadProductsCommand { get; }
    public ICommand SearchCommand { get; }
    public ICommand RefreshCommand { get; }

    public ProductViewModel(IProductService productService)
    {
        _productService = productService;
        Products = new ObservableCollection();

        LoadProductsCommand = new AsyncRelayCommand(LoadProducts);
        SearchCommand = new AsyncRelayCommand(Search);
        RefreshCommand = new AsyncRelayCommand(Refresh);
    }

    private async Task LoadProducts()
    {
        if (IsLoading)
            return;

        try
        {
            IsLoading = true;
            var products = await _productService.GetProductsAsync();
            
            MainThread.BeginInvokeOnMainThread(() =>
            {
                Products.Clear();
                foreach (var product in products)
                {
                    Products.Add(product);
                }
            });
        }
        catch (Exception ex)
        {
            await Application.Current.MainPage.DisplayAlert(
                "Error",
                $"Failed to load products: {ex.Message}",
                "OK");
        }
        finally
        {
            IsLoading = false;
        }
    }

    private async Task Search()
    {
        if (string.IsNullOrWhiteSpace(SearchQuery))
        {
            await LoadProducts();
            return;
        }

        try
        {
            IsLoading = true;
            var results = await _productService.SearchProductsAsync(SearchQuery);
            
            MainThread.BeginInvokeOnMainThread(() =>
            {
                Products.Clear();
                foreach (var product in results)
                {
                    Products.Add(product);
                }
            });
        }
        finally
        {
            IsLoading = false;
        }
    }

    private async Task Refresh()
    {
        SearchQuery = string.Empty;
        await LoadProducts();
    }
}

public abstract class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty(ref T backingStore, T value, 
        [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

**ProductPage.xaml:**




    
        
        
        

        
        

        
        
            
            
                
            

            
                
                    
                        
                        
                            
                            
                            

                            
                            
                                
                                
                                
                                
                                
                            
                        
                    
                
            
        

        
        
            
        
    

### Step 5: Implement Platform-Specific Code

MAUI’s handler system maps cross-platform controls to native components. When you need platform-specific behavior, use conditional compilation:

namespace ProductionMauiApp.Platforms.Android;

public partial class MainActivity : MauiAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        
        // Android-specific initialization
        Window.SetStatusBarColor(Android.Graphics.Color.ParseColor("#007AFF"));
    }
}

#if ANDROID
namespace ProductionMauiApp.Services;

public partial class PlatformService
{
    public string GetDeviceIdentifier()
    {
        var androidId = Android.Provider.Settings.Secure.GetString(
            Android.App.Application.Context.ContentResolver,
            Android.Provider.Settings.Secure.AndroidId);
        
        return androidId;
    }
}
#endif

#if IOS
namespace ProductionMauiApp.Services;

public partial class PlatformService
{
    public string GetDeviceIdentifier()
    {
        return UIKit.UIDevice.CurrentDevice.IdentifierForVendor?.AsString() 
            ?? "unknown";
    }
}
#endif

### Step 6: Implement Dependency Injection and Services

Create a robust service layer that abstracts platform differences:

namespace ProductionMauiApp.Services;

public interface IProductService
{
    Task<IEnumerable> GetProductsAsync();
    Task<IEnumerable> SearchProductsAsync(string query);
    Task GetProductByIdAsync(int id);
}

public class ProductService : IProductService
{
    private readonly HttpClient _httpClient;
    private const string BaseUrl = "https://api.example.com";

    public ProductService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _httpClient.BaseAddress = new Uri(BaseUrl);
        _httpClient.Timeout = TimeSpan.FromSeconds(30);
    }

    public async Task<IEnumerable> GetProductsAsync()
    {
        try
        {
            var response = await _httpClient.GetAsync("/api/products");
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<IEnumerable>(json) 
                ?? Enumerable.Empty();
        }
        catch (HttpRequestException ex)
        {
            Debug.WriteLine($"HTTP Error: {ex.Message}");
            throw;
        }
    }

    public async Task<IEnumerable> SearchProductsAsync(string query)
    {
        var encodedQuery = Uri.EscapeDataString(query);
        var response = await _httpClient.GetAsync($"/api/products/search?q={encodedQuery}");
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<IEnumerable>(json) 
            ?? Enumerable.Empty();
    }

    public async Task GetProductByIdAsync(int id)
    {
        var response = await _httpClient.GetAsync($"/api/products/{id}");
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize(json) 
            ?? throw new InvalidOperationException("Product not found");
    }
}

public record Product(
    int Id,
    string Name,
    string Description,
    decimal Price,
    string ImageUrl);

## Production-Ready C# Examples

### Implementing Resilient HTTP Communication

namespace ProductionMauiApp.Services;

public class ResilientHttpClientFactory
{
    public static HttpClient CreateHttpClient()
    {
        var handler = new HttpClientHandler();

        #if ANDROID
        // Android-specific SSL configuration
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            // Implement certificate pinning for production
            return ValidateCertificatePinning(cert);
        };
        #endif

        var client = new HttpClient(handler)
        {
            Timeout = TimeSpan.FromSeconds(30)
        };

        client.DefaultRequestHeaders.Add("User-Agent", GetUserAgent());
        return client;
    }

    private static string GetUserAgent()
    {
        var version = AppInfo.VersionString;
        var platform = DeviceInfo.Platform.ToString();
        return $"ProductionMauiApp/{version} ({platform})";
    }

    private static bool ValidateCertificatePinning(X509Certificate2 cert)
    {
        // Implement your certificate pinning logic
        const string expectedThumbprint = "YOUR_CERT_THUMBPRINT";
        return cert.Thumbprint == expectedThumbprint;
    }
}

// Register in MauiProgram.cs
builder.Services.AddSingleton(ResilientHttpClientFactory.CreateHttpClient());

### Implementing Offline-First Data Synchronization

namespace ProductionMauiApp.Services;

public interface IDataSyncService
{
    Task SyncAsync();
    Task GetAsync(string key);
    Task SetAsync(string key, T value);
}

public class DataSyncService : IDataSyncService
{
    private readonly IProductService _productService;
    private readonly ISecureStorage _secureStorage;
    private readonly IConnectivity _connectivity;

    public DataSyncService(
        IProductService productService,
        ISecureStorage secureStorage,
        IConnectivity connectivity)
    {
        _productService = productService;
        _secureStorage = secureStorage;
        _connectivity = connectivity;
    }

    public async Task SyncAsync()
    {
        if (!_connectivity.NetworkAccess.HasFlag(NetworkAccess.Internet))
        {
            Debug.WriteLine("No internet connection. Using cached data.");
            return;
        }

        try
        {
            var products = await _productService.GetProductsAsync();
            var json = JsonSerializer.Serialize(products);
            await _secureStorage.SetAsync("products_cache", json);
            await _secureStorage.SetAsync("last_sync", DateTime.UtcNow.ToString("O"));
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Sync failed: {ex.Message}");
        }
    }

    public async Task GetAsync(string key)
    {
        var json = await _secureStorage.GetAsync(key);
        return string.IsNullOrEmpty(json) 
            ? default 
            : JsonSerializer.Deserialize(json);
    }

    public async Task SetAsync(string key, T value)
    {
        var json = JsonSerializer.Serialize(value);
        await _secureStorage.SetAsync(key, json);
    }
}

## Common Pitfalls & Troubleshooting

### Pitfall 1: UI Updates from Background Threads

**Problem:** Updating UI controls from async operations causes crashes.

**Solution:** Always marshal UI updates to the main thread:

// ❌ Wrong
private async Task LoadData()
{
    var data = await _service.GetDataAsync();
    MyLabel.Text = data; // Crash on non-main thread
}

// ✅ Correct
private async Task LoadData()
{
    var data = await _service.GetDataAsync();
    MainThread.BeginInvokeOnMainThread(() =>
    {
        MyLabel.Text = data;
    });
}

### Pitfall 2: Memory Leaks from Event Handlers

**Problem:** Unsubscribed event handlers prevent garbage collection.

**Solution:** Always unsubscribe in `OnDisappearing`:

public partial class MyPage : ContentPage
{
    private void OnPageLoaded(object sender, EventArgs e)
    {
        _viewModel.PropertyChanged += OnPropertyChanged;
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        _viewModel.PropertyChanged -= OnPropertyChanged;
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // Handle property changes
    }
}

### Pitfall 3: Inefficient CollectionView Rendering

**Problem:** Large lists cause performance degradation.

**Solution:** Implement virtualization and use `RecycleElement`:


    
        
    

### Pitfall 4: Platform-Specific Crashes

**Problem:** Code works on one platform but crashes on another.

**Solution:** Test on actual devices and use platform-specific exception handling:

try
{
    #if ANDROID
    var result = await Android.App.Application.Context
        .GetSystemService(Android.Content.Context.SensorService);
    #elif IOS
    var result = UIKit.UIDevice.CurrentDevice.Orientation;
    #endif
}
catch (PlatformNotSupportedException ex)
{
    Debug.WriteLine($"Feature not available on this platform: {ex.Message}");
}

## Performance & Scalability Considerations

### Implement Lazy Loading for Large Datasets

public class LazyLoadingViewModel : BaseViewModel
{
    private readonly IProductService _productService;
    private int _currentPage = 1;
    private const int PageSize = 20;
    private bool _isLoadingMore;

    public ObservableCollection Products { get; } = new();

    public ICommand LoadMoreCommand { get; }

    public LazyLoadingViewModel(IProductService productService)
    {
        _productService = productService;
        LoadMoreCommand = new AsyncRelayCommand(LoadMore);
    }

    private async Task LoadMore()
    {
        if (_isLoadingMore)
            return;

        try
        {
            _isLoadingMore = true;
            var products = await _productService.GetProductsAsync(
                pageNumber: _currentPage,
                pageSize: PageSize);

            MainThread.BeginInvokeOnMainThread(() =>
            {
                foreach (var product in products)
                {
                    Products.Add(product);
                }
            });

            _currentPage++;
        }
        finally
        {
            _isLoadingMore = false;
        }
    }
}

### Optimize Image Loading with Caching

public class CachedImageService
{
    private readonly HttpClient _httpClient;
    private readonly string _cacheDirectory;

    public CachedImageService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _cacheDirectory = Path.Combine(
            FileSystem.CacheDirectory, 
            "images");
        
        Directory.CreateDirectory(_cacheDirectory);
    }

    public async Task GetImageAsync(string url)
    {
        var fileName = GenerateFileName(url);
        var filePath = Path.Combine(_cacheDirectory, fileName);

        if (File.Exists(filePath))
        {
            return ImageSource.FromFile(filePath);
        }

        try
        {
            var response = await _httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode();

            var bytes = await response.Content.ReadAsByteArrayAsync();
            await File.WriteAllBytesAsync(filePath, bytes);

            return ImageSource.FromStream(() => new MemoryStream(bytes));
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Image loading failed: {ex.Message}");
            return null;
        }
    }

    private static string GenerateFileName(string url)
    {
        using var sha256 = System.Security.Cryptography.SHA256.Create();
        var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(url));
        return Convert.ToHexString(hash) + ".jpg";
    }
}

## Practical Best Practices

### 1. Use Dependency Injection Consistently

Always inject dependencies rather than creating instances directly. This enables testing and loose coupling:

// ❌ Avoid
public class ProductViewModel
{
    private readonly IProductService _service = new ProductService();
}

// ✅ Prefer
public class ProductViewModel
{
    private readonly IProductService _service;

    public ProductViewModel(IProductService service)
    {
        _service = service;
    }
}

### 2. Implement Proper Error Handling

public async Task<Result> ExecuteAsync(Func<Task> operation)
{
    try
    {
        var result = await operation();
        return Result.Success(result);
    }
    catch (HttpRequestException ex)
    {
        return Result.Failure($"Network error: {ex.Message}");
    }
    catch (TaskCanceledException ex)
    {
        return Result.Failure("Request timeout");
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Unexpected error: {ex}");
        return Result.Failure("An unexpected error occurred");
    }
}

public record Result(bool IsSuccess, T Data, string ErrorMessage)
{
    public static Result Success(T data) => new(true, data, null);
    public static Result Failure(string error) => new(false, default, error);
}

### 3. Use Async/Await Properly

// ❌ Avoid blocking calls
public void LoadData()
{
    var data = _service.GetDataAsync().Result; // Deadlock risk
}

// ✅ Use async all the way
public async Task LoadData()
{
    var data = await _service.GetDataAsync();
}

// ✅ For fire-and-forget operations
#pragma warning disable CS4014
_ = LoadDataAsync();
#pragma warning restore CS4014

### 4. Implement Proper Logging

public interface ILogger
{
    void Debug(string message);
    void Info(string message);
    void Warning(string message);
    void Error(string message, Exception ex = null);
}

public class ConsoleLogger : ILogger
{
    public void Debug(string message) => 
        System.Diagnostics.Debug.WriteLine($"[DEBUG] {message}");

    public void Info(string message) => 
        System.Diagnostics.Debug.WriteLine($"[INFO] {message}");

    public void Warning(string message) => 
        System.Diagnostics.Debug.WriteLine($"[WARN] {message}");

    public void Error(string message, Exception ex = null) => 
        System.Diagnostics.Debug.WriteLine($"[ERROR] {message}\n{ex}");
}

## Conclusion

You now have a comprehensive foundation for building production-ready cross-platform applications with .NET MAUI. The key takeaways are:

– **Single codebase, multiple platforms:** Write once, deploy everywhere with native performance
– **MVVM architecture:** Separate concerns cleanly for maintainability and testability
– **Dependency injection:** Build loosely coupled, testable components
– **Platform-specific code:** Use conditional compilation for platform-unique features
– **Performance optimization:** Implement lazy loading, caching, and efficient data binding

Your next steps should be:

1. Build a small prototype application to solidify these concepts
2. Explore MAUI’s handler system for advanced customization
3. Implement unit tests using xUnit or NUnit
4. Deploy to actual devices (Android emulator, iOS simulator, or physical devices)
5. Monitor performance using platform-specific profiling tools

The MAUI ecosystem continues to evolve with each .NET release. Stay current with official documentation and community resources as you scale your applications.

—

## Frequently Asked Questions

### Q1: How do I handle platform-specific UI customization without duplicating code?

Use MAUI’s handler system to customize native controls. Handlers map cross-platform controls to native components, allowing you to modify behavior per-platform:

builder.ConfigureEffects(effects =>
{
    #if ANDROID
    Microsoft.Maui.Handlers.ButtonHandler.Mapper.AppendToMapping(
        "CustomButton", 
        (handler, view) =>
        {
            handler.PlatformView.SetAllCaps(false);
        });
    #endif
});

### Q2: What’s the best way to handle navigation between pages?

Implement a navigation service abstraction to decouple ViewModels from navigation logic:

public interface INavigationService
{
    Task NavigateToAsync(IDictionary<string, object> parameters = null);
    Task GoBackAsync();
}

public class NavigationService : INavigationService
{
    public async Task NavigateToAsync(IDictionary<string, object> parameters = null)
    {
        var route = typeof(TViewModel).Name.Replace("ViewModel", "");
        await Shell.Current.GoToAsync(route);
    }

    public async Task GoBackAsync()
    {
        await Shell.Current.GoToAsync("..");
    }
}

### Q3: How do I secure sensitive data like API keys and tokens?

Use `SecureStorage` for sensitive information:

public class SecureTokenService
{
    public async Task SaveTokenAsync(string token)
    {
        await SecureStorage.SetAsync("auth_token", token);
    }

    public async Task GetTokenAsync()
    {
        return await SecureStorage.GetAsync("auth_token");
    }

    public async Task DeleteTokenAsync()
    {
        SecureStorage.Remove("auth_token");
    }
}

### Q4: How do I test MAUI applications effectively?

Use unit tests for ViewModels and services, and integration tests for UI:

public class ProductViewModelTests
{
    [Fact]
    public async Task LoadProducts_ShouldPopulateCollection()
    {
        // Arrange
        var mockService = new Mock();
        var products = new[] { new Product(1, "Test", "Desc", 9.99m, "") };
        mockService.Setup(s => s.GetProductsAsync())
            .ReturnsAsync(products);

        var viewModel = new ProductViewModel(mockService.Object);

        // Act
        await viewModel.LoadProductsCommand.ExecuteAsync(null);

        // Assert
        Assert.Single(viewModel.Products);
        Assert.Equal("Test", viewModel.Products.Name);
    }
}

### Q5: What’s the difference between Shell and traditional navigation?

Shell provides a hierarchical navigation model with tab and flyout support, while traditional navigation uses a stack-based approach. Shell is recommended for most modern applications:




    
        
        
        
    

### Q6: How do I handle background tasks and long-running operations?

Use `BackgroundService` pattern with proper cancellation tokens:

public class SyncBackgroundService : BackgroundService
{
    private readonly IDataSyncService _syncService;
    private readonly ILogger _logger;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await _syncService.SyncAsync();
                await Task.Delay(TimeSpan.FromMinutes(15), stoppingToken);
            }
            catch (OperationCanceledException)
            {
                break;
            }
            catch (Exception ex)
            {
                _logger.Error("Sync failed", ex);
            }
        }
    }
}

### Q7: How do I optimize app startup time?

Defer non-critical initialization and use lazy loading:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        
        builder
            .UseMauiApp()
            // Register only critical services immediately
            .ConfigureServices()
            // Defer heavy initialization
            .ConfigureDeferredServices();

        return builder.Build();
    }

    private static MauiAppBuilder ConfigureDeferredServices(this MauiAppBuilder builder)
    {
        // Register services that can be initialized later
        builder.Services.AddSingleton(
            sp => new AnalyticsService()); // Lazy initialization

        return builder;
    }
}

### Q8: How do I handle different screen sizes and orientations?

Use responsive layouts with `Grid` and `FlexLayout`:


    
    
    
    
    




    
    

### Q9: How do I integrate with native APIs for platform-specific features?

Use partial classes and platform-specific implementations:

// Shared interface
public interface INativeFeatureService
{
    Task GetDeviceInfoAsync();
}

// Shared partial class
public partial class NativeFeatureService : INativeFeatureService
{
    public partial Task GetDeviceInfoAsync();
}

// Android implementation
#if ANDROID
public partial class NativeFeatureService
{
    public partial async Task GetDeviceInfoAsync()
    {
        var deviceId = Android.Provider.Settings.Secure.GetString(
            Android.App.Application.Context.ContentResolver,
            Android.Provider.Settings.Secure.AndroidId);
        
        return await Task.FromResult(deviceId);
    }
}
#endif

// iOS implementation
#if IOS
public partial class NativeFeatureService
{
    public partial async Task GetDeviceInfoAsync()
    {
        var deviceId = UIKit.UIDevice.CurrentDevice.IdentifierForVendor?.AsString();
        return await Task.FromResult(deviceId ?? "unknown");
    }
}
#endif

### Q10: What are the best practices for state management in MAUI?

Use a combination of MVVM, dependency injection, and a state container for complex applications:

public class AppState
{
    public User CurrentUser { get; set; }
    public bool IsAuthenticated { get; set; }
    public List CachedProducts { get; set; } = new();
}

public class StateContainer
{
    private AppState _state = new();
    public event Action OnStateChanged;

    public AppState GetState() => _state;

    public void SetUser(User user)
    {
        _state.CurrentUser = user;
        _state.IsAuthenticated = user != null;
        NotifyStateChanged();
    }

    public void UpdateProducts(List products)
    {
        _state.CachedProducts = products;
        NotifyStateChanged();
    }

    private void NotifyStateChanged() => OnStateChanged?.Invoke();
}

// Register as singleton
builder.Services.AddSingleton();

.NET 8 Enhancements for Performance and AI

The Ultimate Guide to .NET 10 LTS and Performance Optimizations – A Critical Performance Wake-Up Call

AI-Native .NET: Building Intelligent Applications with Azure OpenAI, Semantic Kernel, and ML.NET

.NET Core, 2026 .NET Stack .NET 8, ASP.NET Core, Azure OpenAI, Machine Learning, Microservices Architecture

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Recent Posts

  • Build Stunning Cross-Platform Apps with .NET MAUI
  • .NET 10 Performance Optimization and AOT Compilation
  • .NET 8 Enhancements for Performance and AI
  • Modern Authentication in 2026: How to Secure Your .NET 8 and Angular Apps with Keycloak
  • Mastering .NET 10 and C# 13: Ultimate Guide to High-Performance APIs 🚀

Recent Comments

No comments to show.

Archives

  • February 2026
  • January 2026

Categories

  • .NET Core
  • 2026 .NET Stack
  • Enterprise Architecture
  • Kubernetes
  • Machine Learning
  • Web Development

Sas 101

Copyright © 2026 · saas101.tech · Log in