Help us improve
Share bugs, ideas, or general feedback.
From wpf-dev-pack
Provides guidelines for MVVM in WPF using CommunityToolkit.Mvvm 8.4+ with ObservableProperty attributes, source generators, ViewModels, commands, and project structure.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packHow this skill is triggered — by the user, by Claude, or both
Slash command
/wpf-dev-pack:implementing-communitytoolkit-mvvmsonnetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **MVVM Framework Rule**: `.claude/rules/dotnet/wpf/mvvm-framework.md` 설정에 따라 코드 스타일이 결정됩니다.
Scaffolds WPF project structures with MVVM, DI, and best practices using CommunityToolkit.Mvvm (default) or Prism. Use for new WPF apps, scratch solutions, or setups via /wpf-dev-pack:make-wpf-project.
Building WPF on .NET 8+. Host builder, MVVM Toolkit, Fluent theme, performance, modern C# patterns.
Creates ViewModels, Wizards, and navigation for Avalonia apps using ReactiveUI and Zafiro. Includes patterns for enhanced commands, automatic section discovery, and View-ViewModel mapping.
Share bugs, ideas, or general feedback.
MVVM Framework Rule:
.claude/rules/dotnet/wpf/mvvm-framework.md설정에 따라 코드 스타일이 결정됩니다. Prism 9 사용 시 → PRISM.md 참조
CommunityToolkit.Mvvm 8.4+ 기반 MVVM 패턴 구현 가이드.
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.*" />
</ItemGroup>
MyApp.ViewModels/ ← ViewModel Class Library (UI framework independent)
├── UserViewModel.cs
├── GlobalUsings.cs
└── MyApp.ViewModels.csproj
System.Windows 참조 금지// ✅ Good: Single attribute written inline
[ObservableProperty] private string _userName = string.Empty;
[ObservableProperty] private int _age;
[ObservableProperty] private bool _isActive;
// ✅ Good: Multiple attributes, ObservableProperty always inline
[NotifyPropertyChangedRecipients]
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
[ObservableProperty] private string _email = string.Empty;
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Name is required.")]
[MinLength(2, ErrorMessage = "Name must be at least 2 characters.")]
[ObservableProperty] private string _name = string.Empty;
[NotifyCanExecuteChangedFor(nameof(DeleteCommand))]
[NotifyCanExecuteChangedFor(nameof(UpdateCommand))]
[ObservableProperty] private User? _selectedUser;
// ❌ Bad: ObservableProperty on separate line
[NotifyPropertyChangedRecipients]
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
[ObservableProperty]
private string _email = string.Empty;
namespace MyApp.ViewModels;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public sealed partial class UserViewModel : ObservableObject
{
// Single attribute
[ObservableProperty] private string _firstName = string.Empty;
[ObservableProperty] private string _lastName = string.Empty;
[ObservableProperty] private int _age;
// Multiple attributes — ObservableProperty inline
[NotifyPropertyChangedRecipients]
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
[ObservableProperty] private string _email = string.Empty;
[NotifyCanExecuteChangedFor(nameof(DeleteCommand))]
[NotifyCanExecuteChangedFor(nameof(UpdateCommand))]
[ObservableProperty] private User? _selectedUser;
[RelayCommand(CanExecute = nameof(CanSave))]
private async Task SaveAsync()
{
// Save logic
}
private bool CanSave() => !string.IsNullOrWhiteSpace(Email);
}
[ObservableProperty]를 필드 선언과 같은 줄에 inline 작성[ObservableProperty]는 항상 마지막 줄에 inline.NET 9+ (C# 13)에서는 partial property 문법 사용 가능. field 기반보다 명시적이며 AOT 호환.
// .NET 9+ (C# 13): Partial property syntax
[ObservableProperty] public partial string UserName { get; set; }
// Access modifiers 지원
[ObservableProperty] public partial string Status { get; private set; }
[ObservableProperty] public required partial string Id { get; set; }
[ObservableProperty] public override partial string DisplayName { get; set; }
// Multiple attributes
[NotifyCanExecuteChangedFor(nameof(SaveCommand))]
[ObservableProperty] public partial string Email { get; set; }
8.4.0에서 field 기반 [ObservableProperty] 사용 시 MVVMTK0045 경고 발생:
"Using [ObservableProperty] on fields is not AOT compatible in WinRT scenarios"