From wpf-dev-pack
Guides integration of Wpf.Ui library for Fluent Design in WPF apps, including FluentWindow, NavigationView, SnackbarService, theme setup, and GenericHost DI. Use for modern WPF UIs.
npx claudepluginhub christian289/dotnet-with-claudecode --plugin wpf-dev-packThis skill uses the workspace's default tool permissions.
Wpf.Ui 4.x 기반 Fluent Design WPF 앱 구현 가이드.
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.
Wpf.Ui 4.x 기반 Fluent Design WPF 앱 구현 가이드.
<PackageReference Include="WPF-UI" Version="4.2.*" />
<Application x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<ui:FluentWindow x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="MyApp" Height="600" Width="800"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ui:TitleBar Grid.Row="0" Title="MyApp" />
<ui:NavigationView Grid.Row="1"
x:Name="RootNavigation"
PaneDisplayMode="Left"
IsBackButtonVisible="Collapsed">
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem Content="Home"
TargetPageType="{x:Type local:HomePage}"
Icon="{ui:SymbolIcon Home24}" />
<ui:NavigationViewItem Content="Settings"
TargetPageType="{x:Type local:SettingsPage}"
Icon="{ui:SymbolIcon Settings24}" />
</ui:NavigationView.MenuItems>
</ui:NavigationView>
</Grid>
</ui:FluentWindow>
namespace MyApp;
public partial class MainWindow : FluentWindow
{
public MainWindow(
MainWindowViewModel viewModel,
INavigationService navigationService,
ISnackbarService snackbarService,
IContentDialogService contentDialogService)
{
DataContext = viewModel;
InitializeComponent();
navigationService.SetNavigationControl(RootNavigation);
snackbarService.SetSnackbarPresenter(RootSnackbar);
contentDialogService.SetDialogHost(RootContentDialog);
}
}
namespace MyApp;
public partial class App : Application
{
private static readonly IHost _host = Host.CreateDefaultBuilder()
.ConfigureServices((_, services) =>
{
// Wpf.Ui Services
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<ISnackbarService, SnackbarService>();
services.AddSingleton<IContentDialogService, ContentDialogService>();
services.AddSingleton<IThemeService, ThemeService>();
// Windows
services.AddSingleton<MainWindow>();
services.AddSingleton<MainWindowViewModel>();
// Pages (Transient for navigation)
services.AddTransient<HomePage>();
services.AddTransient<HomeViewModel>();
services.AddTransient<SettingsPage>();
services.AddTransient<SettingsViewModel>();
})
.Build();
protected override async void OnStartup(StartupEventArgs e)
{
await _host.StartAsync();
var mainWindow = _host.Services.GetRequiredService<MainWindow>();
mainWindow.Show();
base.OnStartup(e);
}
protected override async void OnExit(ExitEventArgs e)
{
await _host.StopAsync();
_host.Dispose();
base.OnExit(e);
}
}
// Page는 ui:INavigableView<TViewModel>을 구현
// Page implements ui:INavigableView<TViewModel>
public partial class HomePage : Page, INavigableView<HomeViewModel>
{
public HomeViewModel ViewModel { get; }
public HomePage(HomeViewModel viewModel)
{
ViewModel = viewModel;
DataContext = viewModel;
InitializeComponent();
}
}
// ViewModel에서 INavigationService 주입
// Inject INavigationService in ViewModel
[RelayCommand]
private void NavigateToSettings()
{
_navigationService.Navigate(typeof(SettingsPage));
}
// ViewModel에서 사용
// Use in ViewModel
_snackbarService.Show(
"성공", // Title
"저장되었습니다.", // Message
ControlAppearance.Success,
new SymbolIcon(SymbolRegular.Checkmark24),
TimeSpan.FromSeconds(3));
<ui:SnackbarPresenter x:Name="RootSnackbar" Grid.Row="2" />
// ViewModel에서 사용
// Use in ViewModel
var result = await _contentDialogService.ShowSimpleDialogAsync(
new SimpleContentDialogCreateOptions
{
Title = "삭제 확인",
Content = "정말 삭제하시겠습니까?",
PrimaryButtonText = "삭제",
CloseButtonText = "취소"
});
if (result == ContentDialogResult.Primary)
{
// 삭제 처리
// Handle deletion
}
<ui:ContentDialogService x:Name="RootContentDialog" Grid.Row="1" />
// 테마 전환
// Switch theme
ApplicationThemeManager.Apply(ApplicationTheme.Dark);
ApplicationThemeManager.Apply(ApplicationTheme.Light);
// 시스템 테마 감지 + 자동 적용
// Detect system theme + auto-apply
ApplicationThemeManager.ApplySystemTheme();
WPF-UI는 CommunityToolkit.Mvvm과 자연스럽게 통합됩니다:
public sealed partial class HomeViewModel : ObservableObject
{
private readonly ISnackbarService _snackbarService;
public HomeViewModel(ISnackbarService snackbarService)
{
_snackbarService = snackbarService;
}
[ObservableProperty] private string _searchText = string.Empty;
[RelayCommand]
private void Search()
{
_snackbarService.Show("검색", $"'{SearchText}' 검색 중...",
ControlAppearance.Info, null, TimeSpan.FromSeconds(2));
}
}
FluentWindow 상속 (일반 Window 대신)ExtendsContentIntoTitleBar="True" + ui:TitleBar 조합INavigableView<TViewModel> 구현INavigationService.SetNavigationControl()은 MainWindow 생성자에서 호출