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-packThis skill uses the workspace's default tool permissions.
> **MVVM Framework Rule**: `.claude/rules/dotnet/wpf/mvvm-framework.md` 설정에 따라 코드 스타일이 결정됩니다.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
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"