Avalonia UI
.NET 生态中最成熟的跨平台 UI 框架,用 XAML + C# 构建桌面、移动、Web 应用,像素级一致渲染,被 JetBrains、Unity、GitHub、NASA 使用。
🎯 为什么需要它
WPF 只能在 Windows 上跑,MAUI 的桌面体验差且不支持 Linux。Avalonia 用 Skia 自绘引擎接管整个渲染管线,一套 XAML/C# 代码跑遍 Windows/macOS/Linux/iOS/Android/WebAssembly,像素级一致,性能比 MAUI 快 3-6 倍。
✅ 核心优势
- 真正的全平台:Windows / macOS / Linux / iOS / Android / WebAssembly / 嵌入式 Linux,单一代码库
- 像素级一致渲染:Skia 自绘引擎,不依赖原生控件,每个平台视觉完全一致
- WPF 精神继承者:XAML + C# + MVVM,WPF 开发者几乎零学习成本
- 极致性能:比 MAUI 快 3-6 倍渲染吞吐量,内存占用减半;Impeller 渲染器将 GPU 功耗降低 12 倍
- Linux 一等公民:不是事后补丁,是核心设计目标,支持 X11/Wayland/嵌入式 framebuffer
- 生产级成熟度:10 年+ 开发,2025 年超 210 万项目构建,JetBrains/Unity/GitHub/Samsung/AMD/NASA 使用
- MIT 开源:完全免费,商业友好
⚡ 性能表现
| 指标 | Avalonia | MAUI | WPF |
|---|---|---|---|
| 渲染吞吐量(macOS) | 180 万元素/秒 | 21.2 万元素/秒 | N/A(仅 Windows) |
| 内存占用(Windows) | 约 MAUI 的 50% | 基准 | 与 Avalonia 接近 |
| GPU 功耗(Impeller) | 0.48W | 4.93W | N/A |
| 冷启动 | 快 | 慢(3-5s Android) | 快 |
| 跨平台渲染一致性 | 完全一致 | 不一致(原生控件) | 仅 Windows |
| 启动包体积 | 中等 | 中等 | 大 |
Impeller 渲染器(与 Google Flutter 合作):将 GPU 功耗降低 12 倍,消除帧率抖动,已在 v12 中集成。
🚀 快速上手
环境准备
- .NET 8 SDK 或更高版本
- IDE(任选):
- VS Code(推荐,免费,跨平台)+ Avalonia for VS Code 扩展
- Visual Studio 2022/2026 + Avalonia VS Extension
- JetBrains Rider + AvaloniaRider 插件
安装
# 安装 Avalonia 项目模板
dotnet new install Avalonia.Templates
创建项目
# 基础应用
dotnet new avalonia.app -o MyApp
# MVVM 应用(推荐)
dotnet new avalonia.mvvm -o MyApp
# 进入项目目录
cd MyApp
# 运行
dotnet run
项目结构(MVVM 模板)
MyApp/
├── App.axaml # 应用入口 XAML(资源、样式)
├── App.axaml.cs # 应用代码
├── Program.cs # 入口点
├── ViewModels/
│ └── MainWindowViewModel.cs # ViewModel
├── Views/
│ └── MainWindow.axaml # 主窗口 XAML
│ └── MainWindow.axaml.cs # 主窗口代码
└── MyApp.csproj
最小可运行示例
Views/MainWindow.axaml:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.ViewModels"
xmlns:views="using:MyApp.Views"
x:Class="MyApp.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Title="My Avalonia App"
Width="800" Height="600">
<DockPanel>
<!-- 顶部工具栏 -->
<StackPanel DockPanel.Dock="Top" Margin="10" Orientation="Horizontal">
<TextBlock Text="姓名:" VerticalAlignment="Center"/>
<TextBox Text="{Binding Name}" Width="200" Margin="5,0"/>
<Button Content="问候" Command="{Binding GreetCommand}" Margin="5,0"/>
</StackPanel>
<!-- 内容区域 -->
<TextBlock Text="{Binding Greeting}"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</DockPanel>
</Window>
ViewModels/MainWindowViewModel.cs:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MyApp.ViewModels;
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private string _name = "";
[ObservableProperty]
private string _greeting = "欢迎使用 Avalonia";
[RelayCommand]
private void Greet()
{
Greeting = string.IsNullOrWhiteSpace(Name)
? "请输入姓名"
: $"你好,{Name}!欢迎使用 Avalonia";
}
}
运行:
dotnet run
📦 常用功能速查
布局控件
<!-- DockPanel:停靠布局 -->
<DockPanel>
<TextBlock DockPanel.Dock="Top" Text="顶部"/>
<TextBlock DockPanel.Dock="Left" Text="左侧"/>
<TextBlock Text="填充剩余空间"/>
</DockPanel>
<!-- StackPanel:堆叠布局 -->
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="第一行"/>
<TextBlock Text="第二行"/>
</StackPanel>
<!-- Grid:网格布局 -->
<Grid ColumnDefinitions="*,2*,Auto" RowDefinitions="Auto,*">
<TextBlock Grid.Column="0" Grid.Row="0" Text="左上"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="右上"/>
</Grid>
<!-- WrapPanel:自动换行 -->
<WrapPanel>
<Button Content="A"/>
<Button Content="B"/>
<Button Content="C"/>
</WrapPanel>
数据绑定
<!-- 单向绑定 -->
<TextBlock Text="{Binding UserName}"/>
<!-- 双向绑定 -->
<TextBox Text="{Binding UserName, Mode=TwoWay}"/>
<!-- 绑定到集合 -->
<ListBox ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FullName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- 带转换器的绑定 -->
<TextBlock Text="{Binding BirthDate, Converter={x:Static converters:DateConverters.ToShortDateString}}"/>
DataTemplate(数据模板)
<!-- 基于类型自动匹配 -->
<Window.DataTemplates>
<DataTemplate DataType="vm:PersonViewModel">
<StackPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
<TextBlock Text="{Binding Email}" Foreground="Gray"/>
</StackPanel>
</DataTemplate>
</Window.DataTemplates>
<!-- 显示 ViewModel 集合 -->
<ItemsControl ItemsSource="{Binding People}"/>
样式系统(CSS 风格)
<!-- Avalonia 的样式类似 CSS,不是 WPF 的 Style -->
<Window.Styles>
<!-- 全局样式 -->
<Style Selector="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#333"/>
</Style>
<!-- 类选择器 -->
<Style Selector="Button.primary">
<Setter Property="Background" Value="#0078D4"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<!-- 状态选择器 -->
<Style Selector="Button:pointerover">
<Setter Property="Background" Value="#106EBE"/>
</Style>
<!-- 嵌套选择器 -->
<Style Selector="ListBox ListBoxItem">
<Setter Property="Padding" Value="8"/>
</Style>
</Window.Styles>
<Button Classes="primary" Content="提交"/>
主题
<!-- App.axaml 中引入主题 -->
<Application.Styles>
<!-- Fluent Design(默认) -->
<FluentTheme/>
<!-- 或者 Simple 主题 -->
<!-- <SimpleTheme/> -->
</Application.Styles>
<!-- 动态切换主题 -->
<Application.RequestedThemeVariant>
<RequestedThemeVariant Default="Dark"/>
</Application.RequestedThemeVariant>
对话框
// 使用交互服务(MVVM 推荐方式)
public class MainWindowViewModel : ObservableObject
{
private readonly IClassicDesktopStyleApplicationLifetime _desktop;
[RelayCommand]
private async Task OpenFile()
{
var dialog = new OpenFileDialog
{
Title = "选择文件",
Filters = new List<FileDialogFilter>
{
new() { Name = "图片", Extensions = { "png", "jpg" } },
new() { Name = "所有文件", Extensions = { "*" } }
}
};
var result = await dialog.ShowAsync(_desktop.MainWindow);
if (result is { Length: > 0 })
{
// 处理选中的文件
}
}
[RelayCommand]
private async Task SaveFile()
{
var dialog = new SaveFileDialog
{
Title = "保存文件",
DefaultExtension = "txt"
};
var path = await dialog.ShowAsync(_desktop.MainWindow);
}
}
系统托盘
// 在 App.axaml.cs 中
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
// 系统托盘
var trayIcon = new TrayIcon
{
Icon = new WindowIcon(AssetLoader.Open(new Uri("avares://MyApp/Assets/icon.ico"))),
ToolTipText = "My App",
IsVisible = true
};
trayIcon.Clicked += (_, _) =>
{
desktop.MainWindow.Show();
desktop.MainWindow.Activate();
};
// 托盘菜单
var menu = new NativeMenu();
var showItem = new NativeMenuItem("显示窗口");
showItem.Clicked += (_, _) => desktop.MainWindow.Show();
menu.Add(showItem);
menu.Add(new NativeMenuItem("退出", (_, _) => desktop.Shutdown()));
trayIcon.Menu = menu;
}
}
自定义控件
// 自定义绘制控件
public class RatingControl : Control
{
public static readonly StyledProperty<int> ValueProperty =
AvaloniaProperty.Register<RatingControl, int>(nameof(Value));
public int Value
{
get => GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public override void Render(DrawingContext context)
{
for (int i = 0; i < 5; i++)
{
var brush = i < Value ? Brushes.Gold : Brushes.Gray;
// 绘制星星...
}
}
}
导航模式(MVVM)
<!-- MainWindow.axaml -->
<Window.DataTemplates>
<DataTemplate DataType="vm:HomeViewModel">
<views:HomeView/>
</DataTemplate>
<DataTemplate DataType="vm:SettingsViewModel">
<views:SettingsView/>
</DataTemplate>
</Window.DataTemplates>
<ContentControl Content="{Binding CurrentPage}"/>
// NavigationViewModel.cs
public partial class NavigationViewModel : ObservableObject
{
[ObservableProperty]
private ObservableObject _currentPage;
[RelayCommand]
private void GoHome() => CurrentPage = new HomeViewModel();
[RelayCommand]
private void GoSettings() => CurrentPage = new SettingsViewModel();
}
📋 关键配置
发布单文件
<!-- .csproj -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PublishSingleFile>true</PublishSingleFile>
<TrimMode>full</TrimMode>
<SelfContained>true</SelfContained>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
# 发布
dotnet publish -c Release -r win-x64
dotnet publish -c Release -r osx-arm64
dotnet publish -c Release -r linux-x64
平台特定代码
if (OperatingSystem.IsWindows())
{
// Windows 特定逻辑
}
else if (OperatingSystem.IsMacOS())
{
// macOS 特定逻辑
}
else if (OperatingSystem.IsLinux())
{
// Linux 特定逻辑
}
📦 适用场景
适合:
- 从 WPF 迁移到跨平台(API 最接近,有 XPF 无缝迁移方案)
- 需要 Linux 支持的桌面应用(Avalonia 是 .NET 生态中 Linux 支持最好的)
- 需要像素级一致的跨平台 UI(品牌化界面、设计驱动应用)
- 高性能数据可视化(图表、CAD、媒体工具)
- 嵌入式 Linux 设备 UI(直接渲染到 framebuffer)
- 企业级桌面工具(JetBrains、Unity 都在用)
不适合:
- 移动端优先的应用(虽然支持 iOS/Android,但核心强项在桌面)
- 需要原生平台控件外观的应用(Avalonia 自绘,非原生控件)
- 团队完全没有 XAML/.NET 经验(学习曲线较陡)
- 需要 Web 输出为主的应用(WebAssembly 仍在预览阶段)
⚠️ 已知坑 & 注意事项
- 不是 WPF 1:1 兼容:虽然 API 相似,但样式系统(CSS 风格 vs WPF Style)、模板机制有差异
- 移动端仍在成熟中:iOS/Android 支持可用,但不如 MAUI 的移动端成熟
- WebAssembly 预览中:WebAssembly 目标计划 2026 年 GA,当前仍在预览
- 第三方控件生态较小:相比 WPF/MAUI,第三方控件库选择较少,但 SukiUI 等开源库在快速发展
- XAML 文件扩展名:
.axaml不是.xaml,IDE 需要安装 Avalonia 扩展才能正确识别 - 样式选择器语法:CSS 风格选择器(
Button:pointerover)与 WPF 的Trigger完全不同,需要重新学习 - 编译绑定:使用
x:CompileBindings="True"+x:DataType获得编译时类型检查,但需要正确设置
🆚 竞品对比
| 维度 | Avalonia | WPF | MAUI | Uno Platform | Electron |
|---|---|---|---|---|---|
| 语言 | C# + XAML | C# + XAML | C# + XAML | C# + XAML | JS/TS |
| 渲染 | Skia 自绘 | DirectX | 原生控件 | 原生/Skia | Chromium |
| Windows | ✅ | ✅ | ✅ | ✅ | ✅ |
| macOS | ✅ | ✗ | ✅(Mac Catalyst) | ✅ | ✅ |
| Linux | ✅ | ✗ | ✗ | ✅ | ✅ |
| iOS | ✅ | ✗ | ✅ | ✅ | ✗ |
| Android | ✅ | ✗ | ✅ | ✅ | ✗ |
| WebAssembly | 预览 | ✗ | ✗ | ✅ | ✗ |
| 性能 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 生态成熟度 | 成长期 | 极成熟 | 中等 | 成长期 | 极成熟 |
| WPF 迁移 | 最佳 | — | 困难 | 困难 | 不适用 |
选择建议:
- WPF 应用需要跨平台 → Avalonia(有 XPF 无缝迁移)
- 新项目 + 需要 Linux → Avalonia
- 移动端优先 → MAUI 或 Flutter
- 需要 WebAssembly → Uno Platform
- Windows 专属 → WPF 或 WinUI 3
- 纯 Web 技术栈 → Electron 或 Tauri
🌍 生态 & 社区
- 维护状态:极活跃,v12.0.3(当前最新),每月多个版本
- 文档质量:优秀,官方文档详尽,有完整的教程和示例应用
- 周边生态:
- Avalonia XPF — 无需修改即可在 macOS/Linux 运行现有 WPF 应用(商业版)
- SukiUI — 流行的开源 UI 组件库
- CommunityToolkit.Mvvm — 推荐的 MVVM 框架
- Avalonia DevTools — 实时 UI 调试工具
- Avalonia for VS Code — 官方 VS Code 扩展(XAML 预览、代码补全)
- AvaloniaRider — JetBrains Rider 插件
- 社区活跃度:25k+ Stars,350+ 贡献者,Discord/Telegram/Reddit 社区活跃
💡 引入评估
| 维度 | 评分(/5) | 备注 |
|---|---|---|
| 上手难度 | ⭐⭐⭐⭐ | WPF 开发者几乎零成本,新手需学 XAML |
| 文档完善度 | ⭐⭐⭐⭐ | 教程和示例丰富,但部分高级主题文档较薄 |
| 社区活跃 | ⭐⭐⭐⭐ | 25k Stars,增长迅速,社区响应快 |
| 性能 | ⭐⭐⭐⭐⭐ | 比 MAUI 快 3-6 倍,Impeller 渲染器更是飞跃 |
| 稳定性 | ⭐⭐⭐⭐ | 10 年+ 开发,JetBrains/Unity 生产使用 |
| 综合 | ⭐⭐⭐⭐⭐ | .NET 跨平台 UI 的最佳选择 |
结论:强烈推荐 — Avalonia 是 .NET 生态中跨平台 UI 的事实标准。如果你的团队有 WPF/XAML 经验,或者需要支持 Linux,Avalonia 是最佳选择。性能全面优于 MAUI,渲染一致性无出其右。唯一需注意的是移动端仍在成熟中,移动端优先的项目应评估 MAUI。
推荐引入版本:12.0.3(当前最新稳定版)
🔗 相关链接
- C# .NET WPF XAML 跨平台开发 桌面应用 MAUI
- 官方文档
- GitHub 仓库
- NuGet 包
- Getting Started
- Samples & Tutorials
- Discord
- Avalonia XPF
📝 个人备注
(留白,供后续补充实际使用心得)