Avalonia 避坑经验总结
一、命名空间
1.命名空间差异
<!--WPF-->
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
</Window>
<!--Avalonia-->
<Window xmlns="https://github.com/avaloniaui">
</Window>
2.本地命名空间写法不同
<!--WPF-->
xmlns:local="clr-namespace:myApp"
<!--Avalonia(推荐)-->
xmlns:local="using:myApp"
3.文件扩展名不同
- WPF: .xaml/.xaml.cs
- Avalonia: .axaml/.axaml.cs
二、样式系统
1. 没有Trigger,用选择器+伪类
| WPF(Trigger) | Avalonia(选择器+伪类) |
|---|---|
| Style.Triggers | 伪类 :pointerover,:pressed,:disabled |
| DataTrigger | 绑定伪类[(vm:MyViewModel.IsActive)] |
| EventTrigger | Style.Animations |
| VisualStateManager | 伪类系统 |
| 示例对比 |
<!--WPF DataTrigger-->
<DataTrigger Binding="{Binding IsError}" Value="True">
<Setter Property=Foreground" Value="Red" />
</DataTrigger>
<!--Avalonia:绑定伪类-->
<Style Selector="Border[IsError=true]">
<Setter Property="BorderBrush" Value="Red" />
</Style>
2. 样式用Selector 不用TargetType
<!--WPF-->
<Style TargetType="Button">
<Setter Property="Background" Value="Blue" />
</Style>
<!--Avalonia-->
<Style Selector="Button">
<Setter Property="Background" Value="Blue" />
</Style>
<!--带有类名的样式 类似WPF中指定了Key-->
<Style Selector="Button.primary">
<Setter Property="Background" Value="Blue" />
</Style>
<!--使用时-->
<Button Class="primary" Content="确定" />
3. 没有BaseOn,选择器自动组合
Avalonia 的样式选择器会自动叠加,不需要BaseOn显式继承
三、属性系统:相似但不同
1. DependencyProperty->StyledProperty/DirectProperty
| WPF | Avalonia | 说明 |
|---|---|---|
| DependencyProperty | StyledProperty | 依赖属性:支持样式、动画、继承 |
| - | DirectProperty | 性能更好,但不支持样式、动画 |
| DependencyProperty.Register() | AvaloniaProperty.Register<TOwner,TValue> | 泛型注册 |
注册示例
//WPF
public static readonly DependencyProperty TextProperty=DependencyProperty.Register(nameof(Text),typeof(string),typeof(MyControl),new PropertyMetadata(""));
//Avalonia
public static readonly StyledProperty<string> TextProperty=AvaloniaProperty.Register<MyControl,string>(nameof(Text),defaultValue:"");
2.PasswordBox 的Password 不是依赖属性
坑:想给PasswordBox.Password做双向绑定,结果永远是空
解决方案:用附加属性封装,或直接用事件处理
四、数据绑定:语法有差异
1.绑定语法简写
| WPF | Avalonia | 说明 |
|---|---|---|
| {Binding RelativeSource={RelativeSource Self}} | 绑定自身 | |
| {Binding RelativeSource={RelativeSource AncestorType=Grid}} | 绑定父级 | |
| 绑定控件 | ||
| {Binding RelativeSource={RelativeSource TemplateParent}} | 模板绑定 |
2.编译时绑定(推荐)
Avalonia 支持 CompiledBinding,编译期就能检查绑定错误,强烈建议开启
<Window x:CompileBinding="True">
3. 绑定多打括号会失效
{Binding User.Name()} 多打了(),数据不显示
注意: 绑定属性不能加括号,绑定方法才加括号
五、控件差异:不是1:1 对应
1. 需要额外安装的控件
| 控件 | 说明 |
|---|---|
| DataGrid | 需要安装Avalonia.Controls.DataGrid Nuget 包 |
| TreeView | 内置 HierarchicalDataTemplate 改叫TreeDataTemplate |
2. 没有直接对应的控件
| WPF | Avalonia 替代方案 |
|---|---|
| ListView | 用ListBox+ItemTemplate |
| StatusBar | 自己用Panel样式实现 |
| RichTextBox | 用第三方编辑器 |
| RoutedCommand | 用ICommand实现(推荐CommunityToolkit.Mvvm) |
| WindowsFormsHost | 不支持,必须用Avalonia原生控件 |
3. ToolTip用法不同
<!--WPF-->
<Button ToolTip="提示文字" />
<!--Avalonia-->
<Button ToolTip.Tip="提示文字" />
4.Visibility不同
| WPF | Avalonia | 说明 |
|---|---|---|
| Visibility.Visible | IsVisible="True" | 显示 |
| Visibility.Collapsed | IsVisible="False" | 隐藏且不占空间 |
| Visibility.Hidden | Opcity="0" | 隐藏但占用空间 |
六、资源与资源字典
1.资源引用协议不同
<!--WPF-->
<Image Source="pack://application:,,,/Assets/logo.png" />
<!--Avalonia-->
<Image Source="avares://YourApp/Assets/logo.png" />
2.Build Action 必须设为AvaloniaResource
坑: 新建的XAML 资源文件默认Build Action 是None,启动报错“找不到资源”
解决: 右键文件-属性-生成操作-选择AvaloniaResource
3.StaticResource 必须先定义后引用
坑: WPF会自动查找后面的资源,Avalonia不会
解决: 资源字典合并按依赖顺序排列,或改用DynamicResource
七、布局与跨平台差异
1.StackPanel 嵌套过多会卡顿
坑: Linux 上StackPanel 嵌套3层以上,滚动时CPU飙升
建议:
- 复杂列表用ListBox/DataGrid+虚拟化
- 嵌套不超过2层
- 优先使用Grid
2.SizeToContent 在Linux上不准
坑: SizeToContent="WidthAndHeight" 在Linux上窗口尺寸跑偏
建议: Linux上手动设置固定尺寸,加MaxWidth /MaxHeight 限制
3. TextBox 换行在Linux上有问题
坑: TextWrapping="Wrap" 在Linux 上可能不生效
解决:
- 加 MaxWidth 限制(别用Width=Auto)
- 检查是否被ScrollView包裹(会禁止换行)
4.Canvas 绝对定位跨平台偏移
坑: DPI不同导致Canvas坐标偏移
建议: 优先用Grid+Margin 相对布局,避免Canvas 做复杂布局
八、跨平台常见坑
1、字体乱码
坑: Windows上的“微软雅黑”在Linux/MacOS 上乱码
解决方案:
- 尝试用英文 "Microsoft YaHei"
2. 引用嵌入字体
<FontFamily x:Key="DefaultFont">
avares://YourApp/Fonts/微软雅黑.ttf#微软雅黑,scans-serif
</FontFamily>
3. 加fallback 字体 (如: scan-serif)
4. 图片格式问题
坑: 16位深度PNG 在macOS上不显示
建议: 统一用8位PNG/JPG
5. 日期/数字格式不一致
解决:
- 用StringFormat 显示指定格式
- 全局设置统一文化 Thread.CurrentThread.CurrentCulture=CultureInfo.InvariantCulture
6. TabControl 切换内容丢失
坑: Avalonia默认切换Tab 时卸载内容以节省内存,输入的内容会丢失
解决:
<TabControl KeepAlive="True" />
7. Popup 点击外部不关闭
坑: Popup 直接放在Window下,StaysOpen="False" 不生效
解决: 把Popup放在Grid /StackPanel 等容器内
九、线程与调度
1. 后台线程直接用 Collection.Add(item) 抛异常
解决:
Application.Current.Dispatcher.Invoke(()=>collection.Add(item))
2. Dispatcher API略有不同
| WPF | Avalonia |
|---|---|
| Dispatcher.Invoke() | Dispatcher.UIThread.InvokeAsync() |
| Dispatcher.BeginInvoke() | Dispatcher.UIThread.Post() |
| Dispatcher.CheckAccess() | Dispacher.UIThread.CheckAccess() |

浙公网安备 33010602011771号