maui-blazor-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

.NET MAUI Blazor Hybrid Development

.NET MAUI Blazor Hybrid开发

Expert guidance for building cross-platform apps with .NET MAUI and Blazor.
针对使用.NET MAUI和Blazor构建跨平台应用的专家指导。

Implementation Workflow

实现工作流

1. Analysis Phase (Required)

1. 分析阶段(必填)

Before implementation, determine:
  • App type: Pure MAUI Blazor or MAUI + Blazor Web App (shared UI)
  • Platform targets: Android, iOS, Windows, macOS
  • Native features needed: Sensors, camera, file system, notifications
  • State management: Component state, MVVM, or hybrid approach
  • Navigation pattern: Blazor-only, Shell, or mixed navigation
在实施前,需确定:
  • 应用类型:纯MAUI Blazor应用 或 MAUI + Blazor Web应用(共享UI)
  • 目标平台:Android、iOS、Windows、macOS
  • 所需原生功能:传感器、相机、文件系统、通知
  • 状态管理:组件状态、MVVM或混合方式
  • 导航模式:仅Blazor导航、Shell导航或混合导航

2. Architecture Decision

架构决策

ScenarioRecommended Approach
Mobile-first with some web
maui-blazor
template
Shared UI across mobile + web
maui-blazor-web
template with RCL
Complex native integrationMVVM with platform services
Simple data-driven UIComponent state with DI services
场景推荐方案
移动端优先,兼顾Web
maui-blazor
模板
移动端与Web共享UI搭配RCL的
maui-blazor-web
模板
复杂原生集成结合平台服务的MVVM模式
简单数据驱动UI依赖DI服务的组件状态管理

3. Project Setup

3. 项目设置

csharp
// MauiProgram.cs - Essential setup
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        });

    builder.Services.AddMauiBlazorWebView();
#if DEBUG
    builder.Services.AddBlazorWebViewDeveloperTools();
#endif

    // Register services
    builder.Services.AddSingleton<IDeviceService, DeviceService>();
    builder.Services.AddScoped<IDataService, DataService>();

    return builder.Build();
}
csharp
// MauiProgram.cs - Essential setup
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        });

    builder.Services.AddMauiBlazorWebView();
#if DEBUG
    builder.Services.AddBlazorWebViewDeveloperTools();
#endif

    // Register services
    builder.Services.AddSingleton<IDeviceService, DeviceService>();
    builder.Services.AddScoped<IDataService, DataService>();

    return builder.Build();
}

4. BlazorWebView Configuration

4. BlazorWebView配置

xml
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui">
    <b:BlazorWebView HostPage="wwwroot/index.html">
        <b:BlazorWebView.RootComponents>
            <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </b:BlazorWebView.RootComponents>
    </b:BlazorWebView>
</ContentPage>
xml
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui">
    <b:BlazorWebView HostPage="wwwroot/index.html">
        <b:BlazorWebView.RootComponents>
            <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </b:BlazorWebView.RootComponents>
    </b:BlazorWebView>
</ContentPage>

Core Patterns

核心模式

Dependency Injection

依赖注入

LifetimeUse Case
AddSingleton<T>
App-wide state, device services, settings
AddScoped<T>
Per-BlazorWebView instance state
AddTransient<T>
Stateless utilities, factories
csharp
// Interface for platform-specific implementation
public interface IDeviceService
{
    string GetDeviceModel();
    Task<bool> HasPermissionAsync(string permission);
}

// Platform implementation registered in MauiProgram.cs
builder.Services.AddSingleton<IDeviceService, DeviceService>();
生命周期使用场景
AddSingleton<T>
应用全局状态、设备服务、设置
AddScoped<T>
每个BlazorWebView实例的状态
AddTransient<T>
无状态工具类、工厂类
csharp
// Interface for platform-specific implementation
public interface IDeviceService
{
    string GetDeviceModel();
    Task<bool> HasPermissionAsync(string permission);
}

// Platform implementation registered in MauiProgram.cs
builder.Services.AddSingleton<IDeviceService, DeviceService>();

Component Lifecycle

组件生命周期

csharp
@code {
    [Parameter] public string Id { get; set; } = "";

    // Called once when component initializes
    protected override async Task OnInitializedAsync()
    {
        await LoadDataAsync();
    }

    // Called when parameters change (including first render)
    protected override void OnParametersSet()
    {
        // React to parameter changes
    }

    // Called after each render
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            // JS interop safe here
        }
    }
}
csharp
@code {
    [Parameter] public string Id { get; set; } = "";

    // Called once when component initializes
    protected override async Task OnInitializedAsync()
    {
        await LoadDataAsync();
    }

    // Called when parameters change (including first render)
    protected override void OnParametersSet()
    {
        // React to parameter changes
    }

    // Called after each render
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            // JS interop safe here
        }
    }
}

Platform Feature Access

平台功能访问

csharp
// Check platform and access native features
@inject IDeviceService DeviceService

@if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
    <AndroidSpecificComponent />
}

@code {
    private async Task AccessCameraAsync()
    {
        var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
        if (status != PermissionStatus.Granted)
        {
            status = await Permissions.RequestAsync<Permissions.Camera>();
        }

        if (status == PermissionStatus.Granted)
        {
            // Use camera
        }
    }
}
csharp
// Check platform and access native features
@inject IDeviceService DeviceService

@if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
    <AndroidSpecificComponent />
}

@code {
    private async Task AccessCameraAsync()
    {
        var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
        if (status != PermissionStatus.Granted)
        {
            status = await Permissions.RequestAsync<Permissions.Camera>();
        }

        if (status == PermissionStatus.Granted)
        {
            // Use camera
        }
    }
}

State Updates from External Events

外部事件触发的状态更新

csharp
@implements IDisposable
@inject IDataService DataService

<p>@message</p>

@code {
    private string message = "";

    protected override void OnInitialized()
    {
        DataService.OnDataChanged += HandleDataChanged;
    }

    private async void HandleDataChanged(object? sender, EventArgs e)
    {
        message = "Data updated!";
        await InvokeAsync(StateHasChanged); // Required for external events
    }

    public void Dispose()
    {
        DataService.OnDataChanged -= HandleDataChanged;
    }
}
csharp
@implements IDisposable
@inject IDataService DataService

<p>@message</p>

@code {
    private string message = "";

    protected override void OnInitialized()
    {
        DataService.OnDataChanged += HandleDataChanged;
    }

    private async void HandleDataChanged(object? sender, EventArgs e)
    {
        message = "Data updated!";
        await InvokeAsync(StateHasChanged); // Required for external events
    }

    public void Dispose()
    {
        DataService.OnDataChanged -= HandleDataChanged;
    }
}

Reference Documentation

参考文档

For detailed patterns and examples, see:
  • Project Structure: Solution templates, RCL setup, multi-targeting
  • Blazor Components: Lifecycle, RenderFragment, EventCallback, data binding
  • Platform Integration: Device APIs, permissions, platform-specific code
  • Navigation & Routing: Blazor routing, Shell, deep linking
  • State Management: MVVM, DI patterns, CommunityToolkit.Mvvm
如需详细的模式和示例,请参阅:
  • 项目结构:解决方案模板、RCL设置、多目标平台配置
  • Blazor组件:生命周期、RenderFragment、EventCallback、数据绑定
  • 平台集成:设备API、权限、平台特定代码
  • 导航与路由:Blazor路由、Shell、深度链接
  • 状态管理:MVVM、DI模式、CommunityToolkit.Mvvm

Quick Reference

快速参考

Common Service Registration

常见服务注册

csharp
// Services
builder.Services.AddSingleton<ISettingsService, SettingsService>();
builder.Services.AddSingleton<IConnectivity>(Connectivity.Current);
builder.Services.AddSingleton<IGeolocation>(Geolocation.Default);

// ViewModels (if using MVVM)
builder.Services.AddTransient<MainViewModel>();
builder.Services.AddTransient<SettingsViewModel>();

// Pages with DI
builder.Services.AddTransient<MainPage>();
csharp
// Services
builder.Services.AddSingleton<ISettingsService, SettingsService>();
builder.Services.AddSingleton<IConnectivity>(Connectivity.Current);
builder.Services.AddSingleton<IGeolocation>(Geolocation.Default);

// ViewModels (if using MVVM)
builder.Services.AddTransient<MainViewModel>();
builder.Services.AddTransient<SettingsViewModel>();

// Pages with DI
builder.Services.AddTransient<MainPage>();

Platform Checks

平台检查

csharp
// Runtime platform check
if (DeviceInfo.Current.Platform == DevicePlatform.iOS) { }
if (DeviceInfo.Current.Platform == DevicePlatform.Android) { }
if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) { }
if (DeviceInfo.Current.Platform == DevicePlatform.macOS) { }

// Compile-time platform check
#if ANDROID
    // Android-specific code
#elif IOS
    // iOS-specific code
#elif WINDOWS
    // Windows-specific code
#endif
csharp
// Runtime platform check
if (DeviceInfo.Current.Platform == DevicePlatform.iOS) { }
if (DeviceInfo.Current.Platform == DevicePlatform.Android) { }
if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) { }
if (DeviceInfo.Current.Platform == DevicePlatform.macOS) { }

// Compile-time platform check
#if ANDROID
    // Android-specific code
#elif IOS
    // iOS-specific code
#elif WINDOWS
    // Windows-specific code
#endif

Navigation Patterns

导航模式

csharp
// Blazor navigation (within BlazorWebView)
@inject NavigationManager Navigation
Navigation.NavigateTo("/details/123");

// MAUI navigation (to other pages)
await Navigation.PushAsync(new SettingsPage());
await Shell.Current.GoToAsync("//settings");
csharp
// Blazor navigation (within BlazorWebView)
@inject NavigationManager Navigation
Navigation.NavigateTo("/details/123");

// MAUI navigation (to other pages)
await Navigation.PushAsync(new SettingsPage());
await Shell.Current.GoToAsync("//settings");