.NET MAUI 跨平台:一套代码多端运行

FreeGuideOnline 最新 2026-06-18

.NET MAUI 跨平台入门:用一套代码征服多端

在移动与桌面应用开发领域,多平台重复造轮子一直是团队效率的隐形杀手。.NET MAUI(Multi-platform App UI)的出现彻底改变了这一局面——它允许你使用单一的 C# 和 XAML 代码库,构建同时运行于 Android、iOS、macOS、Windows 以及 Tizen 的原生应用。本教程将从零开始,带你掌握 .NET MAUI 的核心概念与实战流程,让“Write Once, Run Anywhere”不再是一句口号。

先决条件与开发环境

开始之前,请确认你的开发机满足以下要求:

  • 操作系统:Windows 10 1809+(推荐 Windows 11)或 macOS 11+(用于 iOS/macOS 构建)
  • 开发工具:Visual Studio 2022 17.3+(需安装“.NET Multi-platform App UI 开发”工作负载),或 JetBrains Rider 2022.2+,也可使用命令行 + VS Code
  • SDK:.NET 6 或 .NET 7/8(MAUI 从 .NET 6 开始正式支持)
  • 硬件:至少 8 GB 内存,并开启 Hyper-V(Windows)或通过 Mac 构建机(iOS)

安装完工作负载后,打开终端执行以下命令验证环境:

dotnet workload list

maui 出现在列表中,即表示环境就绪。

第一个 .NET MAUI 项目

创建项目

在 Visual Studio 中选择“创建新项目” -> 搜索“MAUI” -> 选取“.NET MAUI 应用”。也可以通过 CLI 创建:

dotnet new maui -n MyFirstMauiApp
cd MyFirstMauiApp

项目结构解析

生成的项目包含以下关键文件:

  • MauiProgram.cs:应用入口,类似 Main,负责配置服务、字体、平台特定初始化。
  • App.xaml / App.xaml.cs:定义全局资源字典,并通过 Application.Current 访问。
  • AppShell.xaml:基于 Shell 的导航结构,管理页面路由、Flyout 菜单和 Tab。
  • MainPage.xaml:默认首页,用于展示 UI。
  • Platforms/ 文件夹:存放各平台的入口代码(Android 的 MainApplication、iOS 的 AppDelegate 等),通常无需手动修改。

运行项目,你将看到一个带有“Hello, World!”和计数器按钮的默认应用。

跨平台 UI 设计:XAML 与控件

MAUI 提供了一套丰富的跨平台控件,它们会自动渲染为各平台的原生等效控件。例如:

  • <Button> 在 Android 上是 Material Design 按钮,在 iOS 上则是 UIKit 的 UIButton
  • <Label><Entry><ListView> 等均遵循统一抽象。

布局系统

使用灵活的布局容器构建自适应界面:

<ContentPage xmlns="...">
    <Grid ColumnDefinitions="*, 2*" RowDefinitions="Auto, *">
        <BoxView Color="Blue" Grid.Row="0" Grid.Column="0" />
        <VerticalStackLayout Grid.Row="1" Grid.Column="1" Spacing="10">
            <Label Text="欢迎使用 MAUI" FontSize="24" HorizontalOptions="Center"/>
            <Button Text="点击我" Clicked="OnButtonClicked"/>
        </VerticalStackLayout>
    </Grid>
</ContentPage>

MAUI 支持 HorizontalStackLayoutVerticalStackLayoutGridFlexLayoutAbsoluteLayout,组合使用可应对绝大多数布局场景。

数据绑定与 MVVM 模式

MAUI 内置强大的数据绑定引擎,与 MVVM 模式天然契合。以下是一个简单的双向绑定示例:

ViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }
    // INotifyPropertyChanged implementation...
}

XAML 绑定:

<Entry Text="{Binding Name, Mode=TwoWay}" Placeholder="输入你的名字" />
<Label Text="{Binding Name, StringFormat='你好, {0}!'}" />

MauiProgram.cs 中注册 ViewModel 与页面,并使用依赖注入:

builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<MainViewModel>();

然后在页面构造函数中接收 ViewModel 并设置 BindingContext

导航与 Shell

使用 Shell 可实现复杂的导航结构,而无需手动管理导航栈。

定义路由:

<Shell ...>
    <FlyoutItem Title="首页" Icon="home.png">
        <ShellContent ContentTemplate="{DataTemplate local:MainPage}" Route="main" />
    </FlyoutItem>
    <FlyoutItem Title="详情" Icon="detail.png">
        <ShellContent ContentTemplate="{DataTemplate local:DetailPage}" Route="detail" />
    </FlyoutItem>
</Shell>

代码导航:

await Shell.Current.GoToAsync("detail?itemId=42");

接收参数时,为目标页面的 QueryProperty 装饰:

[QueryProperty(nameof(ItemId), "itemId")]
public partial class DetailPage : ContentPage
{
    public string ItemId { get; set; }
}

处理平台差异:条件编译与部分类

即使 MAUI 让大部分代码共享,有时仍需调用平台特定的 API 或调整行为。

条件编译:

#if ANDROID
    // 调用 Android 特有功能
#elif IOS
    // 调用 iOS 特有功能
#endif

部分类与平台文件夹: 为需要平台实现的类创建一个共享的抽象类,然后在 Platforms/AndroidPlatforms/iOS 等目录下添加对应的部分类文件。例如定义 IBatteryInfo 接口,各平台分别实现,最后通过依赖注入注册。

MAUI 也内置了大量实用 API(如连接性、地理定位、传感器等),大多封装在 Microsoft.Maui.Devices 等命名空间下,只需调用通用 API 即可,无需自行编写平台代码。

访问原生 API 与第三方库

当内置 API 无法满足需求时,可以使用 .NET for Android/iOS/macOS 的绑定方式直接调用原生 SDK。例如,在 MAUI 项目中直接引用 Xamarin.Firebase.*Plugin.Maui.Audio 等 NuGet 包,它们会帮你处理平台隔离。

示例:播放音频

var player = AudioManager.Current.CreatePlayer(await FileSystem.OpenAppPackageFileAsync("sound.mp3"));
player.Play();

第三方库生态日益丰富,常见的有:

  • CommunityToolkit.Maui:补充控件、动画和行为
  • SkiaSharp:跨平台 2D 图形渲染
  • ZXing.Net.Maui:条码扫描

自定义控件与处理程序

MAUI 的渲染层通过处理程序将虚拟控件映射到原生视图。你可以修改现有控件的处理程序或创建全新的自定义控件。

自定义控件示例(RatingView):

public class RatingView : View
{
    public static readonly BindableProperty ValueProperty = ...;
    public int Value { get; set; }
}

然后为各平台实现 IRatingViewHandler,在 MauiProgram.cs 中注册:

builder.ConfigureMauiHandlers(handlers =>
{
    handlers.AddHandler<RatingView, RatingViewHandler>();
});

调试与多平台测试

Visual Studio 集成了多种调试手段:

  • 热重载:修改 XAML 或 C# 代码后无需重新部署即可看到效果。
  • XAML 实时可视化树:检查运行时 UI 树结构与属性。
  • 平台目标切换:从工具栏直接选择 Android 模拟器、iOS 模拟器(需要 Mac 连接)、Windows 本地应用等。

对于 UI 测试,可以使用 UITestAppium 编写跨平台的自动化测试脚本。

应用打包与发布

MAUI 项目通过 dotnet publish 命令完成打包,各平台输出标准包格式:

  • Android.apk.aab (Google Play)
  • iOS.ipa (需使用 macOS 的 Archive 流程,并通过 Xcode 或 Transporter 上传)
  • Windows:MSIX 包或纯 .exe
  • macOS.app 包(需代码签名)

配置版本号、签名证书等都可以在项目 .csproj 文件中通过 MSBuild 属性完成。

例如构建 Android 的发行包:

dotnet publish -f net8.0-android -c Release -p:AndroidPackageFormats=apk

常见问题与最佳实践

  1. 性能优化:尽量使用 CollectionView 替代 ListView,启用虚拟化;异步加载数据,避免阻塞 UI 线程。
  2. 图片资源:将 SVG 或 PNG 放在 Resources/Images 中,MAUI 自动生成多平台尺寸,无需手动切图。
  3. 字体图标:引入字体文件(如 FontAwesome),在 MauiProgram.cs 中注册,然后以标签形式使用。
  4. 应用生命周期:通过 Application.Current 的事件(如 SleepResume)管理前后台切换。
  5. 避免过多嵌套布局:优先选择相对简单的布局组合,减少布局传递次数。

结语

.NET MAUI 不仅是一个 UI 框架,它更是一套完整的跨平台构建生态。从 UI 抽象、数据绑定、导航到原生 API 调用,一切都围绕“代码共享最大化”展开。你只需写一次业务逻辑和界面,就能在六个主流平台上获得原生体验。随着 .NET 8 及后续版本的长周期支持,现在正是投入学习 MAUI 的最佳时机。

即刻动手,用 dotnet new maui 开启你的跨平台之旅吧!