关于 avalonia-mvvm
avalonia-mvvm 是一份在 Avalonia 应用中使用 CommunityToolkit.Mvvm 模式的指南,涵盖 ViewModel、导航、命令、验证和依赖注入。
主要功能
- 01使用 ObservableObject 构建 ViewModel
- 02通过特性创建可观察属性
- 03实现同步和异步命令
- 04使用 DataTemplates 映射 View 与 ViewModel
- 05通过依赖注入传递服务
- 06添加属性验证
适用场景
- 01为 Avalonia 视图创建 ViewModel
- 02添加可通知 UI 的属性和命令
- 03设置由 ViewModel 驱动的导航
- 04验证 ViewModel 属性
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ abdssamie/ quater --skill avalonia-mvvm安装后在 Claude Code 中输入/avalonia-mvvm确认已加载。
详细介绍
Avalonia 中的 MVVM 模式
在 Avalonia 应用程序中使用 CommunityToolkit.Mvvm 的 MVVM 模式完整指南。
我能做什么
- 指导如何使用 ObservableObject 基类实现 ViewModel
- 展示如何使用 [ObservableProperty] 特性创建可观察属性
- 演示包含异步和 CanExecute 的 [RelayCommand] 命令模式
- 说明如何使用 DataTemplates 将 View 映射到 ViewModel(对导航至关重要)
- 展示如何通过依赖注入将服务传递给 ViewModel
何时使用我
在需要以下操作时使用此技能:
- 为 Avalonia 视图创建新的 ViewModel
- 实现可观察属性,以便在属性变化时通知 UI
- 添加命令以处理用户交互(按钮点击等)
- 使用 SukiSideMenu 或 ContentControl 设置导航模式
- 在 ViewModel 之间传递服务(例如 ISukiToastManager)
- 为 ViewModel 属性实现验证
ViewModel 基类
基本 ViewModel
using CommunityToolkit.Mvvm.ComponentModel;
namespace YourApp.ViewModels;
public partial class ViewModelBase : ObservableObject
{
}
页面 ViewModel 基类
using CommunityToolkit.Mvvm.ComponentModel;
namespace YourApp.ViewModels;
public abstract partial class PageViewModelBase : ViewModelBase
{
public abstract string DisplayName { get; }
public abstract string Icon { get; }
}
可观察属性
基本可观察属性
[ObservableProperty]
private string _name = "";
带验证的属性
using System.ComponentModel.DataAnnotations;
[ObservableProperty]
[Required(ErrorMessage = "Name is required")]
[MinLength(3, ErrorMessage = "Name must be at least 3 characters")]
private string _name = "";
带属性变更通知的属性
[ObservableProperty]
private string _firstName = "";
[ObservableProperty]
private string _lastName = "";
public string FullName => $"{FirstName} {LastName}";
partial void OnFirstNameChanged(string value)
{
OnPropertyChanged(nameof(FullName));
}
partial void OnLastNameChanged(string value)
{
OnPropertyChanged(nameof(FullName));
}
命令
基本命令
[RelayCommand]
private void Save()
{
// Save logic
}
带参数的命令
[RelayCommand]
private void ButtonClick(string buttonName)
{
LastButtonClicked = buttonName;
}
视图:
<Button Content="Save"
Command="{Binding ButtonClickCommand}"
CommandParameter="Save Button" />
异步命令
[RelayCommand]
private async Task LoadDataAsync()
{
IsLoading = true;
await Task.Delay(1000);
IsLoading = false;
}
带 CanExecute 的命令
[ObservableProperty]
private bool _isDataLoaded;
[RelayCommand(CanExecute = nameof(CanSave))]
private void Save()
{
// Save logic
}
private bool CanSave() => IsDataLoaded;
partial void OnIsDataLoadedChanged(bool value)
{
SaveCommand.NotifyCanExecuteChanged();
}
关键模式:DataTemplates
使用导航模式将 ViewModel 显示在 ContentControl 中(例如 SukiSideMenu)时,必须定义 DataTemplates,将 ViewModel 映射到对应的 View。
在 SukiWindow 中:
<suki:SukiWindow.DataTemplates>
<DataTemplate DataType="vm:HomePageViewModel">
<views:HomePage />
</DataTemplate>
<DataTemplate DataType="vm:SettingsPageViewModel">
<views:SettingsPage />
</DataTemplate>
</suki:SukiWindow.DataTemplates>
依赖注入
将服务传递给 ViewModel
父级 ViewModel:
public partial class MainWindowViewModel : ViewModelBase
{
private readonly ISukiToastManager _toastManager;
public MainWindowViewModel()
{
_toastManager = new SukiToastManager();
Pages = new ObservableCollection<PageViewModelBase>
{
new NotificationsPageViewModeler)
};
}
}
子级 ViewModel:
public partial class NotificationsPageViewModel : PageViewModelBase
{
private readonly ISukiToastManager _toastManager;
public NotificationsPageViewModel(ISukiToastManager toastManager)
{
_toastManager = toastManager;
}
}
应避免的常见错误
- 忘记定义 DataTemplates——没有 ViewModel 到 View 的映射,导航将无法工作
- 未使用 partial 类——CommunityToolkit.Mvvm 要求使用 partial 关键字
- 缺少 OnPropertyChanged——没有手动通知,计算属性不会更新
- 未调用 NotifyCanEuteChanged——带 CanExecute 的命令不会自动重新评估
- 字段命名错误——可观察属性对应的字段必须以一个下划线开头,并声明为 private
最佳实践
- 始终在 ViewModel 上使用 partial 关键字
- 使用 [ObservableProperty],而不是手动实现 INotifyPropertyChanged
- 使用 [RelayCommand],而不是手动实现 ICommand
- 在根窗口中定义 DataTemplates,以支持导航场景
- 通过构造函数注入传递服务
- 使用计算属性获取派生值
- 为需要验证的属性添加验证特性
评论
支持 Markdown