Desktop UI

WPF UI — сучасна бібліотека Fluent контролів

Інтеграція WPF UI (Wpf.Ui) у додатки: сучасні контроли Windows 11, NavigationView, Mica/Acrylic ефекти, темна тема, та повна екосистема Fluent Design

WPF UI — сучасна бібліотека Fluent контролів

Офіційна Fluent тема від Microsoft (PresentationFramework.Fluent) надає базові стилі для стандартних WPF контролів, але має обмеження: немає нових контролів з Windows 11 (NavigationView, InfoBar, CardControl), немає справжніх Mica/Acrylic ефектів, обмежена кастомізація. Саме тут на сцену виходить WPF UI (пакет Wpf.Ui) — потужна open-source бібліотека, яка надає повноцінну екосистему Fluent Design для WPF додатків.

WPF UI — це не просто набір стилів, а комплексне рішення для створення сучасних Windows 11 додатків у WPF. Бібліотека включає десятки нових контролів (NavigationView для sidebar navigation, CardControl для card-based layouts, InfoBar для notifications), справжні Mica та Acrylic ефекти через Windows API, вбудовану систему тем з підтримкою світлої/темної/системної теми, та навіть MVVM-friendly сервіси для навігації та діалогів. Це найближче, що ви можете отримати до WinUI 3 досвіду, залишаючись у WPF.

У цій статті ми детально розглянемо, як інтегрувати WPF UI у ваш додаток, як використовувати нові контроли, як налаштувати Mica/Acrylic ефекти, як працює система навігації, як створювати власні стилі на базі WPF UI, та як мігрувати існуючий WPF додаток на WPF UI. Ми також порівняємо WPF UI з офіційною Fluent темою та іншими альтернативами (ModernWpf, MahApps.Metro), щоб ви могли зробити інформований вибір для вашого проєкту.

Словник термінів
  • WPF UI (Wpf.Ui) — open-source бібліотека Fluent контролів для WPF
  • NavigationView — контрол для sidebar navigation (як у Windows Settings)
  • Mica — напівпрозорий матеріал Windows 11 з subtle texture
  • Acrylic — напівпрозорий матеріал з blur ефектом
  • InfoBar — контрол для показу notifications/alerts
  • CardControl — контейнер з elevation для card-based layouts
  • ThemeService — сервіс для управління темами
  • NavigationService — сервіс для програмної навігації
  • SymbolIcon — іконки з Segoe Fluent Icons шрифту

Чому WPF UI замість офіційної Fluent теми?

Перш ніж заглибитися у технічні деталі, важливо зрозуміти переваги WPF UI порівняно з офіційною PresentationFramework.Fluent.

Порівняльна таблиця

ФункціональністьPresentationFramework.FluentWPF UI (Wpf.Ui)
Базові стилі✅ Rounded corners, сучасні кольори✅ Повна Fluent Design System
Нові контроли❌ Тільки стандартні WPF контроли✅ 30+ нових контролів (NavigationView, InfoBar, CardControl)
Mica/Acrylic❌ Немає✅ Справжні ефекти через Windows API
Темна тема✅ Базова підтримка✅ Повна підтримка з автоматичним перемиканням
Навігація❌ Потрібно реалізовувати вручну✅ Вбудований NavigationService
Іконки❌ Потрібні сторонні рішення✅ Вбудовані Segoe Fluent Icons
MVVM підтримка❌ Немає спеціальних сервісів✅ NavigationService, DialogService, SnackbarService
Документація⚠️ Мінімальна✅ Детальна з прикладами
Активна розробка⚠️ Базова підтримка✅ Активний розвиток, часті оновлення
Розмір0 KB (вбудовано у .NET)~2 MB (NuGet пакет)
СкладністьПроста (один рядок)Середня (налаштування + навчання)

Коли використовувати що?

PresentationFramework.Fluent — якщо:

  • Потрібен мінімальний overhead (немає додаткових залежностей)
  • Використовуєте тільки стандартні WPF контроли
  • Не потрібні складні navigation patterns
  • Простий додаток без багато екранів

WPF UI — якщо:

  • Потрібні сучасні контроли (NavigationView, InfoBar, CardControl)
  • Хочете справжні Mica/Acrylic ефекти
  • Складний додаток з багатьма екранами та навігацією
  • Потрібна повна екосистема Fluent Design
  • Готові витратити час на навчання бібліотеки

Рекомендація: Для нових проєктів з вимогами до сучасного UI — WPF UI. Для простих додатків або швидкої модернізації — офіційна Fluent тема.

Установка та базова інтеграція

Розпочнемо з установки WPF UI та базової конфігурації.

Крок 1: Установка NuGet пакету

dotnet add package Wpf.Ui

Або через Package Manager Console:

Install-Package Wpf.Ui

Або через Visual Studio: Tools → NuGet Package Manager → Manage NuGet Packages → Search "Wpf.Ui"

Поточна версія: 3.x (перевірте GitHub для останньої версії)

Крок 2: Підключення тем у App.xaml

<Application x:Class="MyWPFApp.App"
             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"
             StartupUri="Views/MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- WPF UI Theme -->
                <ui:ThemesDictionary Theme="Light" />
                
                <!-- WPF UI Controls -->
                <ui:ControlsDictionary />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Важливо:

  • ThemesDictionary — базові кольори та стилі теми
  • ControlsDictionary — стилі для всіх контролів
  • Обидва потрібні для правильної роботи

Крок 3: Налаштування MainWindow

WPF UI надає спеціальний FluentWindow замість стандартного Window:

<ui:FluentWindow x:Class="MyWPFApp.Views.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="My WPF UI App" 
                 Height="600" 
                 Width="1000"
                 ExtendsContentIntoTitleBar="True"
                 WindowBackdropType="Mica"
                 WindowCornerPreference="Round">
    
    <Grid>
        <!-- Content -->
        <TextBlock Text="Hello WPF UI!" 
                   FontSize="24"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center" />
    </Grid>
    
</ui:FluentWindow>

Code-behind:

using Wpf.Ui.Controls;

namespace MyWPFApp.Views;

public partial class MainWindow : FluentWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

Ключові властивості FluentWindow:

  • ExtendsContentIntoTitleBar — контент заходить у title bar (як у Windows 11 додатках)
  • WindowBackdropType — тип фону (None, Mica, Acrylic, Tabbed)
  • WindowCornerPreference — форма кутів (Default, DoNotRound, Round, RoundSmall)

Крок 4: Перевірка результату

Запустіть додаток. Ви побачите:

  • Вікно з rounded corners (Windows 11 style)
  • Mica backdrop (напівпрозорий фон з subtle texture)
  • Сучасний title bar
  • Fluent стилі для всіх контролів
Mica ефектMica — це новий матеріал Windows 11, який створює напівпрозорий фон з subtle texture. Він адаптується до desktop wallpaper користувача, створюючи відчуття інтеграції з системою.Mica працює тільки на Windows 11. На Windows 10 автоматично fallback до solid color.Для Acrylic ефекту (більш виражена прозорість з blur) використовуйте:
WindowBackdropType="Acrylic"

Одна з найпотужніших можливостей WPF UI — це NavigationView, контрол для створення sidebar navigation як у Windows Settings.

Базова структура з NavigationView

<ui:FluentWindow x:Class="MyWPFApp.Views.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="My App" 
                 Height="600" 
                 Width="1000"
                 ExtendsContentIntoTitleBar="True"
                 WindowBackdropType="Mica">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        
        <!-- Title Bar -->
        <ui:TitleBar Grid.Row="0" 
                     Title="My Application"
                     Icon="pack://application:,,,/Assets/icon.png" />
        
        <!-- Navigation -->
        <ui:NavigationView Grid.Row="1"
                           x:Name="NavigationView"
                           IsBackButtonVisible="Collapsed"
                           IsPaneToggleVisible="True"
                           OpenPaneLength="250">
            
            <!-- Menu Items -->
            <ui:NavigationView.MenuItems>
                <ui:NavigationViewItem Content="Home"
                                       Icon="{ui:SymbolIcon Home24}"
                                       TargetPageType="{x:Type local:HomePage}" />
                
                <ui:NavigationViewItem Content="Dashboard"
                                       Icon="{ui:SymbolIcon DataUsage24}"
                                       TargetPageType="{x:Type local:DashboardPage}" />
                
                <ui:NavigationViewItem Content="Settings"
                                       Icon="{ui:SymbolIcon Settings24}"
                                       TargetPageType="{x:Type local:SettingsPage}" />
                
                <ui:NavigationViewItemSeparator />
                
                <ui:NavigationViewItem Content="About"
                                       Icon="{ui:SymbolIcon Info24}"
                                       TargetPageType="{x:Type local:AboutPage}" />
            </ui:NavigationView.MenuItems>
            
            <!-- Footer Items -->
            <ui:NavigationView.FooterMenuItems>
                <ui:NavigationViewItem Content="Profile"
                                       Icon="{ui:SymbolIcon Person24}"
                                       TargetPageType="{x:Type local:ProfilePage}" />
            </ui:NavigationView.FooterMenuItems>
            
            <!-- Content Frame -->
            <Frame x:Name="ContentFrame" />
            
        </ui:NavigationView>
    </Grid>
    
</ui:FluentWindow>

Code-behind з NavigationService:

using Wpf.Ui.Controls;

namespace MyWPFApp.Views;

public partial class MainWindow : FluentWindow
{
    public MainWindow()
    {
        InitializeComponent();
        
        // Налаштування навігації
        NavigationView.SetNavigationViewService(
            new Wpf.Ui.Services.NavigationService(ContentFrame));
        
        // Навігація на початкову сторінку
        NavigationView.Navigate(typeof(HomePage));
    }
}

Створення сторінок для навігації

HomePage.xaml:

<Page x:Class="MyWPFApp.Views.HomePage"
      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="Home">
    
    <Grid Margin="20">
        <StackPanel>
            <TextBlock Text="Welcome to My App" 
                       Style="{StaticResource TitleTextBlockStyle}"
                       Margin="0,0,0,20" />
            
            <ui:CardControl>
                <StackPanel>
                    <TextBlock Text="Getting Started" 
                               FontSize="18"
                               FontWeight="SemiBold"
                               Margin="0,0,0,10" />
                    <TextBlock Text="This is a modern WPF application built with WPF UI library."
                               TextWrapping="Wrap"
                               Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
                </StackPanel>
            </ui:CardControl>
        </StackPanel>
    </Grid>
    
</Page>

HomePage.xaml.cs:

using System.Windows.Controls;

namespace MyWPFApp.Views;

public partial class HomePage : Page
{
    public HomePage()
    {
        InitializeComponent();
    }
}

Тепер при кліку на menu items у NavigationView автоматично відбувається навігація між сторінками.

Програмна навігація

Для програмної навігації (наприклад, з кнопки або ViewModel):

// У MainWindow або через DI
private readonly INavigationService _navigationService;

public void NavigateToSettings()
{
    _navigationService.Navigate(typeof(SettingsPage));
}

// Навігація назад
public void GoBack()
{
    if (_navigationService.CanGoBack)
    {
        _navigationService.GoBack();
    }
}

Нові контроли WPF UI

WPF UI надає десятки нових контролів. Розглянемо найкорисніші.

CardControl — контейнер з elevation

<ui:CardControl Margin="10">
    <StackPanel>
        <TextBlock Text="Card Title" 
                   FontSize="18"
                   FontWeight="SemiBold"
                   Margin="0,0,0,10" />
        <TextBlock Text="Card content goes here. Cards are great for grouping related information."
                   TextWrapping="Wrap" />
        <ui:Button Content="Action" 
                   Appearance="Primary"
                   HorizontalAlignment="Right"
                   Margin="0,10,0,0" />
    </StackPanel>
</ui:CardControl>

Властивості:

  • Автоматичний elevation (тінь)
  • Rounded corners
  • Hover effect
  • Адаптується до теми

InfoBar — notifications та alerts

<ui:InfoBar Title="Success"
            Message="Your changes have been saved successfully."
            Severity="Success"
            IsOpen="True"
            IsClosable="True"
            Margin="10" />

<ui:InfoBar Title="Warning"
            Message="This action cannot be undone."
            Severity="Warning"
            IsOpen="True"
            Margin="10" />

<ui:InfoBar Title="Error"
            Message="An error occurred while processing your request."
            Severity="Error"
            IsOpen="True"
            Margin="10" />

<ui:InfoBar Title="Information"
            Message="New features are available in this version."
            Severity="Informational"
            IsOpen="True"
            Margin="10" />

Severity types:

  • Informational — синій (за замовчуванням)
  • Success — зелений
  • Warning — жовтий/помаранчевий
  • Error — червоний

Button з Appearance

WPF UI розширює стандартну кнопку:

<StackPanel Orientation="Horizontal" Spacing="10">
    <!-- Primary Button -->
    <ui:Button Content="Primary" 
               Appearance="Primary" />
    
    <!-- Secondary Button -->
    <ui:Button Content="Secondary" 
               Appearance="Secondary" />
    
    <!-- Transparent Button -->
    <ui:Button Content="Transparent" 
               Appearance="Transparent" />
    
    <!-- Danger Button -->
    <ui:Button Content="Danger" 
               Appearance="Danger" />
    
    <!-- Icon Button -->
    <ui:Button Icon="{ui:SymbolIcon Add24}" 
               Appearance="Primary" />
    
    <!-- Button with Icon and Text -->
    <ui:Button Content="Add Item"
               Icon="{ui:SymbolIcon Add24}"
               Appearance="Primary" />
</StackPanel>

SymbolIcon — вбудовані іконки

WPF UI включає Segoe Fluent Icons:

<StackPanel Orientation="Horizontal" Spacing="10">
    <ui:SymbolIcon Symbol="Home24" FontSize="24" />
    <ui:SymbolIcon Symbol="Settings24" FontSize="24" />
    <ui:SymbolIcon Symbol="Person24" FontSize="24" />
    <ui:SymbolIcon Symbol="Mail24" FontSize="24" />
    <ui:SymbolIcon Symbol="Calendar24" FontSize="24" />
</StackPanel>

Доступні сотні іконок. Повний список: Fluent UI System Icons

TextBox з ClearButton

<ui:TextBox PlaceholderText="Enter your name"
            Icon="{ui:SymbolIcon Person24}"
            ClearButtonEnabled="True"
            Width="300" />

<ui:PasswordBox PlaceholderText="Enter password"
                Icon="{ui:SymbolIcon LockClosed24}"
                Width="300"
                Margin="0,10,0,0" />

NumberBox — числовий input

<ui:NumberBox Value="50"
              Minimum="0"
              Maximum="100"
              SpinButtonPlacementMode="Inline"
              Width="200" />

Rating — зірковий рейтинг

<ui:Rating Value="3.5"
           Maximum="5"
           IsReadOnly="False" />

ProgressRing — індикатор завантаження

<ui:ProgressRing IsIndeterminate="True" 
                 Width="50" 
                 Height="50" />

Система тем та ThemeService

WPF UI має вбудовану систему управління темами з підтримкою світлої, темної та системної теми.

Налаштування ThemeService

App.xaml.cs:

using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using Wpf.Ui;

namespace MyWPFApp;

public partial class App : Application
{
    private IServiceProvider _serviceProvider;
    
    public App()
    {
        // Налаштування DI
        var services = new ServiceCollection();
        ConfigureServices(services);
        _serviceProvider = services.BuildServiceProvider();
    }
    
    private void ConfigureServices(IServiceCollection services)
    {
        // WPF UI Services
        services.AddSingleton<IThemeService, ThemeService>();
        services.AddSingleton<ISnackbarService, SnackbarService>();
        services.AddSingleton<IDialogService, DialogService>();
        services.AddSingleton<INavigationService, NavigationService>();
        
        // Views
        services.AddSingleton<MainWindow>();
        services.AddTransient<HomePage>();
        services.AddTransient<SettingsPage>();
        
        // ViewModels
        services.AddTransient<MainViewModel>();
        services.AddTransient<SettingsViewModel>();
    }
    
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        
        var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
        mainWindow.Show();
    }
}

Використання ThemeService

using Wpf.Ui;
using Wpf.Ui.Appearance;

public class SettingsViewModel : ViewModelBase
{
    private readonly IThemeService _themeService;
    
    public SettingsViewModel(IThemeService themeService)
    {
        _themeService = themeService;
        
        // Отримати поточну тему
        CurrentTheme = _themeService.GetTheme();
        
        ChangeThemeCommand = new RelayCommand<string>(ChangeTheme);
    }
    
    public ApplicationTheme CurrentTheme { get; private set; }
    
    public ICommand ChangeThemeCommand { get; }
    
    private void ChangeTheme(string themeName)
    {
        var theme = themeName switch
        {
            "Light" => ApplicationTheme.Light,
            "Dark" => ApplicationTheme.Dark,
            _ => ApplicationTheme.Unknown // System default
        };
        
        _themeService.SetTheme(theme);
        CurrentTheme = theme;
    }
}

UI для перемикання теми

<ui:CardControl Header="Appearance">
    <StackPanel>
        <TextBlock Text="Choose your theme"
                   Margin="0,0,0,10"
                   Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
        
        <StackPanel Orientation="Horizontal" Spacing="10">
            <ui:Button Content="Light"
                       Icon="{ui:SymbolIcon WeatherSunny24}"
                       Command="{Binding ChangeThemeCommand}"
                       CommandParameter="Light" />
            
            <ui:Button Content="Dark"
                       Icon="{ui:SymbolIcon WeatherMoon24}"
                       Command="{Binding ChangeThemeCommand}"
                       CommandParameter="Dark" />
            
            <ui:Button Content="System"
                       Icon="{ui:SymbolIcon Desktop24}"
                       Command="{Binding ChangeThemeCommand}"
                       CommandParameter="System" />
        </StackPanel>
    </StackPanel>
</ui:CardControl>

Автоматичне слідування за системною темою

public class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        
        var themeService = _serviceProvider.GetRequiredService<IThemeService>();
        
        // Встановити системну тему
        themeService.SetTheme(ApplicationTheme.Unknown); // Unknown = System default
        
        // Слідкувати за змінами системної теми
        SystemThemeWatcher.Watch(
            this,
            WindowBackdropType.Mica,
            updateAccents: true);
    }
}

Mica та Acrylic ефекти

WPF UI надає справжні Mica та Acrylic ефекти через Windows API.

Mica Background

<ui:FluentWindow WindowBackdropType="Mica">
    <!-- Content -->
</ui:FluentWindow>

Типи Mica:

  • Mica — стандартний Mica (адаптується до wallpaper)
  • MicaAlt — альтернативний Mica (більш subtle)
  • Tabbed — для tabbed interfaces

Acrylic Background

<ui:FluentWindow WindowBackdropType="Acrylic">
    <!-- Content -->
</ui:FluentWindow>

Acrylic створює більш виражений blur ефект ніж Mica.

Програмне налаштування backdrop

using Wpf.Ui.Appearance;

public partial class MainWindow : FluentWindow
{
    public MainWindow()
    {
        InitializeComponent();
        
        // Встановити Mica
        WindowBackdrop.ApplyBackdrop(this, WindowBackdropType.Mica);
        
        // Або Acrylic
        // WindowBackdrop.ApplyBackdrop(this, WindowBackdropType.Acrylic);
    }
}

Acrylic для окремих елементів

Можна застосувати acrylic до окремих контролів:

<Border Background="{DynamicResource ApplicationBackgroundBrush}"
        CornerRadius="8"
        Padding="20">
    <Border.Effect>
        <ui:AcrylicEffect TintColor="#80FFFFFF" 
                          TintOpacity="0.8"
                          NoiseOpacity="0.03" />
    </Border.Effect>
    
    <StackPanel>
        <TextBlock Text="Acrylic Panel" 
                   FontSize="18"
                   FontWeight="SemiBold" />
        <TextBlock Text="This panel has acrylic effect"
                   Margin="0,10,0,0" />
    </StackPanel>
</Border>
Обмеження Mica/Acrylic
  • Windows 11 only: Mica працює тільки на Windows 11. На Windows 10 fallback до solid color.
  • Performance: Acrylic може впливати на продуктивність, особливо на слабких GPU. Використовуйте обережно.
  • Accessibility: Напівпрозорі фони можуть погіршити читабельність для користувачів з проблемами зору. Завжди тестуйте контраст.
Для production додатків рекомендується:
  • Mica для main window (легкий, не впливає на продуктивність)
  • Acrylic тільки для dialogs/popups (короткочасне використання)
  • Можливість вимкнути ефекти у Settings для accessibility

SnackbarService та DialogService

WPF UI надає сервіси для показу notifications та діалогів.

SnackbarService — toast notifications

Налаштування у MainWindow:

<ui:FluentWindow>
    <Grid>
        <!-- Content -->
        
        <!-- Snackbar Presenter (зазвичай внизу) -->
        <ui:SnackbarPresenter x:Name="SnackbarPresenter"
                              VerticalAlignment="Bottom"
                              HorizontalAlignment="Center"
                              Margin="0,0,0,20" />
    </Grid>
</ui:FluentWindow>

Code-behind:

public partial class MainWindow : FluentWindow
{
    private readonly ISnackbarService _snackbarService;
    
    public MainWindow(ISnackbarService snackbarService)
    {
        InitializeComponent();
        
        _snackbarService = snackbarService;
        _snackbarService.SetSnackbarPresenter(SnackbarPresenter);
    }
}

Використання у ViewModel:

public class HomeViewModel : ViewModelBase
{
    private readonly ISnackbarService _snackbarService;
    
    public HomeViewModel(ISnackbarService snackbarService)
    {
        _snackbarService = snackbarService;
        
        SaveCommand = new RelayCommand(Save);
    }
    
    public ICommand SaveCommand { get; }
    
    private async void Save()
    {
        // Симуляція збереження
        await Task.Delay(1000);
        
        // Показати success notification
        _snackbarService.Show(
            "Success",
            "Your changes have been saved.",
            ControlAppearance.Success,
            new SymbolIcon(SymbolRegular.Checkmark24),
            TimeSpan.FromSeconds(3));
    }
}

Типи Snackbar:

// Success
_snackbarService.Show("Success", "Operation completed", ControlAppearance.Success);

// Warning
_snackbarService.Show("Warning", "Please review your input", ControlAppearance.Caution);

// Error
_snackbarService.Show("Error", "Something went wrong", ControlAppearance.Danger);

// Info
_snackbarService.Show("Info", "New features available", ControlAppearance.Info);

DialogService — модальні діалоги

Налаштування:

public partial class MainWindow : FluentWindow
{
    private readonly IDialogService _dialogService;
    
    public MainWindow(IDialogService dialogService)
    {
        InitializeComponent();
        
        _dialogService = dialogService;
        _dialogService.SetDialogHost(this); // MainWindow як host для діалогів
    }
}

Простий діалог:

public async Task ShowSimpleDialog()
{
    var result = await _dialogService.ShowSimpleDialogAsync(
        new SimpleContentDialogCreateOptions
        {
            Title = "Confirm Delete",
            Content = "Are you sure you want to delete this item? This action cannot be undone.",
            PrimaryButtonText = "Delete",
            SecondaryButtonText = "Cancel",
            CloseButtonText = null
        });
    
    if (result == ContentDialogResult.Primary)
    {
        // Користувач натиснув Delete
        DeleteItem();
    }
}

Custom діалог з ViewModel:

<!-- Views/Dialogs/EditUserDialog.xaml -->
<ui:ContentDialog x:Class="MyWPFApp.Views.Dialogs.EditUserDialog"
                  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="Edit User"
                  PrimaryButtonText="Save"
                  SecondaryButtonText="Cancel">
    
    <StackPanel Width="400">
        <ui:TextBox PlaceholderText="Name"
                    Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
                    Margin="0,0,0,10" />
        
        <ui:TextBox PlaceholderText="Email"
                    Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}"
                    Margin="0,0,0,10" />
        
        <ui:NumberBox PlaceholderText="Age"
                      Value="{Binding Age}"
                      Minimum="0"
                      Maximum="150" />
    </StackPanel>
    
</ui:ContentDialog>
// Показати custom діалог
var dialog = new EditUserDialog
{
    DataContext = new EditUserViewModel(currentUser)
};

var result = await _dialogService.ShowAsync(dialog);

if (result == ContentDialogResult.Primary)
{
    // Користувач натиснув Save
    var viewModel = (EditUserViewModel)dialog.DataContext;
    SaveUser(viewModel.Name, viewModel.Email, viewModel.Age);
}

Кастомізація стилів

WPF UI дозволяє кастомізувати кольори та стилі.

Зміна accent color

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ui:ThemesDictionary Theme="Light" />
            <ui:ControlsDictionary />
        </ResourceDictionary.MergedDictionaries>
        
        <!-- Custom Accent Color -->
        <Color x:Key="SystemAccentColor">#6B46C1</Color>
        <Color x:Key="SystemAccentColorSecondary">#553C9A</Color>
        <Color x:Key="SystemAccentColorTertiary">#44307A</Color>
        
        <SolidColorBrush x:Key="SystemAccentBrush" Color="{StaticResource SystemAccentColor}" />
        <SolidColorBrush x:Key="SystemAccentBrushSecondary" Color="{StaticResource SystemAccentColorSecondary}" />
        <SolidColorBrush x:Key="SystemAccentBrushTertiary" Color="{StaticResource SystemAccentColorTertiary}" />
    </ResourceDictionary>
</Application.Resources>

Власні стилі з BasedOn

<!-- Custom Primary Button -->
<Style x:Key="LargePrimaryButtonStyle" 
       TargetType="ui:Button" 
       BasedOn="{StaticResource {x:Type ui:Button}}">
    <Setter Property="Appearance" Value="Primary" />
    <Setter Property="FontSize" Value="16" />
    <Setter Property="Padding" Value="24,12" />
    <Setter Property="MinWidth" Value="150" />
</Style>

<!-- Custom Card -->
<Style x:Key="HighlightCardStyle" 
       TargetType="ui:CardControl" 
       BasedOn="{StaticResource {x:Type ui:CardControl}}">
    <Setter Property="BorderBrush" Value="{DynamicResource SystemAccentBrush}" />
    <Setter Property="BorderThickness" Value="2" />
</Style>

Організація стилів

Для великих проєктів:

Styles/
├── Colors.xaml
├── Typography.xaml
├── Buttons.xaml
├── Cards.xaml
└── Theme.xaml

Theme.xaml:

<ResourceDictionary 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">
    
    <ResourceDictionary.MergedDictionaries>
        <!-- WPF UI Base -->
        <ui:ThemesDictionary Theme="Light" />
        <ui:ControlsDictionary />
        
        <!-- Custom Styles -->
        <ResourceDictionary Source="Colors.xaml" />
        <ResourceDictionary Source="Typography.xaml" />
        <ResourceDictionary Source="Buttons.xaml" />
        <ResourceDictionary Source="Cards.xaml" />
    </ResourceDictionary.MergedDictionaries>
    
</ResourceDictionary>

Міграція з офіційної Fluent теми

Якщо ви вже використовуєте PresentationFramework.Fluent, міграція на WPF UI проста.

Крок 1: Замінити ResourceDictionary

Було:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml" />
</ResourceDictionary.MergedDictionaries>

Стало:

<ResourceDictionary.MergedDictionaries>
    <ui:ThemesDictionary Theme="Light" />
    <ui:ControlsDictionary />
</ResourceDictionary.MergedDictionaries>

Крок 2: Замінити Window на FluentWindow

Було:

<Window x:Class="MyApp.MainWindow">

Стало:

<ui:FluentWindow x:Class="MyApp.MainWindow"
                 WindowBackdropType="Mica">

Крок 3: Оновити стилі кнопок

Було:

<Style x:Key="PrimaryButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Background" Value="{DynamicResource SystemAccentBrush}" />
</Style>

Стало:

<ui:Button Appearance="Primary" />
<!-- Або -->
<Style x:Key="PrimaryButtonStyle" TargetType="ui:Button" BasedOn="{StaticResource {x:Type ui:Button}}">
    <Setter Property="Appearance" Value="Primary" />
</Style>

Крок 4: Додати нові можливості

Тепер можна використовувати:

  • NavigationView для sidebar
  • CardControl для cards
  • InfoBar для notifications
  • SymbolIcon для іконок

Практичні завдання

Рівень 1: Базова інтеграція WPF UI

Завдання: Створіть WPF додаток з WPF UI, NavigationView та 3 сторінками.

Вимоги:

  • FluentWindow з Mica backdrop
  • NavigationView з 3 menu items (Home, Dashboard, Settings)
  • Кожна сторінка має CardControl з контентом
  • Використання SymbolIcon для menu items

Критерії успіху:

  • Навігація працює
  • Mica ефект видимий (на Windows 11)
  • Всі контроли мають Fluent стилі

Рівень 2: Теми та сервіси

Завдання: Додайте підтримку тем, SnackbarService та DialogService.

Вимоги:

  • ThemeService з можливістю перемикання Light/Dark/System
  • SnackbarService для показу notifications
  • DialogService для підтвердження дій
  • Settings сторінка з UI для перемикання теми

Критерії успіху:

  • Тема змінюється при виборі
  • Snackbar показується при діях користувача
  • Dialog показується перед видаленням

Рівень 3: Повноцінний додаток

Завдання: Створіть повноцінний CRUD додаток з WPF UI.

Вимоги:

  • NavigationView з 5+ сторінками
  • CRUD операції з Entity Framework Core
  • SnackbarService для feedback
  • DialogService для підтвердження
  • InfoBar для важливих повідомлень
  • CardControl для відображення items
  • Власні стилі з BasedOn
  • Підтримка обох тем

Критерії успіху:

  • Повна функціональність CRUD
  • Професійний вигляд
  • Smooth навігація
  • Правильна обробка помилок з UI feedback

Порівняння з альтернативами

WPF UI — не єдина бібліотека для модернізації WPF. Розглянемо альтернативи.

WPF UI vs ModernWpf

ModernWpf — інша популярна бібліотека для Fluent Design у WPF.

ХарактеристикаWPF UIModernWpf
Активність✅ Активний розвиток⚠️ Менш активний
Windows 11 features✅ Mica, rounded corners⚠️ Базова підтримка
Нові контроли✅ NavigationView, InfoBar, CardControl✅ NavigationView, InfoBar
Документація✅ Детальна⚠️ Базова
Розмір~2 MB~1.5 MB
СтильWindows 11 FluentWindows 10 Fluent
Сумісність.NET 6+.NET Framework 4.6.2+

Висновок: WPF UI більш сучасний та активно розвивається. ModernWpf підходить якщо потрібна підтримка .NET Framework.

WPF UI vs MahApps.Metro

MahApps.Metro — старша бібліотека з Metro/Modern UI стилями.

ХарактеристикаWPF UIMahApps.Metro
СтильFluent Design (Windows 11)Metro Design (Windows 8)
Сучасність✅ Дуже сучасний⚠️ Застарілий вигляд
Контроли✅ Багато нових✅ Багато, але старі
Hamburger Menu✅ NavigationView✅ HamburgerMenu
СкладністьСередняВисока
Документація✅ Детальна✅ Детальна

Висновок: MahApps.Metro застарів візуально. Для нових проєктів WPF UI краще.

WPF UI vs HandyControl

HandyControl — китайська бібліотека з великою колекцією контролів.

ХарактеристикаWPF UIHandyControl
СтильFluent DesignCustom (схожий на Material)
Кількість контролів~30~80+
ДокументаціяАнглійськаПереважно китайська
Windows 11 integration✅ Mica, Acrylic❌ Немає
СкладністьСередняВисока

Висновок: HandyControl має більше контролів, але WPF UI краще інтегрується з Windows 11.

Рекомендації

Використовуйте WPF UI якщо:

  • Потрібен сучасний Windows 11 вигляд
  • Важлива Mica/Acrylic підтримка
  • Потрібна NavigationView
  • Активна підтримка важлива

Використовуйте ModernWpf якщо:

  • Потрібна підтримка .NET Framework
  • Достатньо Windows 10 стилю

Використовуйте MahApps.Metro якщо:

  • Вже використовуєте у існуючому проєкті
  • Потрібні специфічні контроли MahApps

Використовуйте HandyControl якщо:

  • Потрібна велика колекція контролів
  • Не важливий Windows 11 native вигляд

Best Practices

Підсумуємо найкращі практики роботи з WPF UI.

1. Використовуйте Dependency Injection

WPF UI сервіси (ThemeService, NavigationService, DialogService) розроблені для DI:

// Налаштування DI
services.AddSingleton<IThemeService, ThemeService>();
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<IDialogService, DialogService>();
services.AddSingleton<ISnackbarService, SnackbarService>();

Це дозволяє легко тестувати та підтримувати код.

2. Організуйте структуру проєкту

MyWPFApp/
├── Views/
│   ├── Pages/
│   │   ├── HomePage.xaml
│   │   ├── DashboardPage.xaml
│   │   └── SettingsPage.xaml
│   ├── Dialogs/
│   │   └── EditUserDialog.xaml
│   └── MainWindow.xaml
├── ViewModels/
│   ├── HomeViewModel.cs
│   ├── DashboardViewModel.cs
│   └── SettingsViewModel.cs
├── Models/
├── Services/
├── Styles/
│   ├── Colors.xaml
│   ├── Typography.xaml
│   └── Theme.xaml
└── App.xaml

3. Використовуйте CardControl для групування

Замість Border використовуйте CardControl:

<!-- Погано -->
<Border Background="White" CornerRadius="8" Padding="16">
    <StackPanel>
        <!-- Content -->
    </StackPanel>
</Border>

<!-- Добре -->
<ui:CardControl>
    <StackPanel>
        <!-- Content -->
    </StackPanel>
</ui:CardControl>

CardControl автоматично адаптується до теми та має правильний elevation.

4. Використовуйте Appearance для кнопок

Замість власних стилів використовуйте вбудовані Appearance:

<!-- Погано -->
<Button Background="Blue" Foreground="White" />

<!-- Добре -->
<ui:Button Appearance="Primary" />

5. Використовуйте SymbolIcon замість зображень

Замість PNG/SVG іконок використовуйте SymbolIcon:

<!-- Погано -->
<Image Source="/Assets/home.png" Width="24" Height="24" />

<!-- Добре -->
<ui:SymbolIcon Symbol="Home24" FontSize="24" />

SymbolIcon автоматично адаптується до теми та має кращу якість.

6. Тестуйте на обох темах

Завжди тестуйте додаток у світлій та темній темі:

// У тестах або debug mode
#if DEBUG
    _themeService.SetTheme(ApplicationTheme.Dark);
#endif

7. Використовуйте DynamicResource для кольорів

<!-- Погано -->
<TextBlock Foreground="Black" />

<!-- Добре -->
<TextBlock Foreground="{DynamicResource TextFillColorPrimaryBrush}" />

8. Обробляйте відсутність Windows 11

Mica працює тільки на Windows 11. Додайте fallback:

public MainWindow()
{
    InitializeComponent();
    
    // Перевірка Windows 11
    if (Environment.OSVersion.Version.Build >= 22000)
    {
        WindowBackdrop.ApplyBackdrop(this, WindowBackdropType.Mica);
    }
    else
    {
        // Fallback для Windows 10
        Background = new SolidColorBrush(Colors.White);
    }
}

Обмеження та проблеми

WPF UI має деякі обмеження, про які важливо знати.

1. Тільки .NET 6+

WPF UI вимагає .NET 6 або новіше. Не працює на .NET Framework.

Рішення: Мігруйте на .NET 6/7/8 або використовуйте ModernWpf.

2. Mica тільки на Windows 11

Mica ефект працює тільки на Windows 11 build 22000+.

Рішення: Додайте fallback для Windows 10 (solid color або gradient).

3. Performance з Acrylic

Acrylic може впливати на продуктивність на слабких GPU.

Рішення: Використовуйте Mica замість Acrylic для main window. Acrylic тільки для dialogs.

4. Конфлікти з іншими UI бібліотеками

WPF UI може конфліктувати з MahApps.Metro, ModernWpf, HandyControl.

Рішення: Не змішуйте UI бібліотеки. Виберіть одну.

5. Розмір додатку

WPF UI додає ~2 MB до розміру додатку.

Рішення: Для мінімальних додатків використовуйте офіційну Fluent тему. Для повноцінних — 2 MB не критично.

Резюме

WPF UI — це найпотужніша бібліотека для створення сучасних Windows 11 додатків у WPF. Основні переваги:

Повна екосистема Fluent Design: Не просто стилі, а комплексне рішення з новими контролами (NavigationView, InfoBar, CardControl), справжніми Mica/Acrylic ефектами, вбудованою системою тем, та MVVM-friendly сервісами.

Справжні Windows 11 ефекти: Mica та Acrylic працюють через Windows API, створюючи справжній native вигляд. Це неможливо з офіційною Fluent темою.

Активний розвиток: Бібліотека активно розвивається, регулярні оновлення, детальна документація, велика спільнота. Це важливо для довгострокових проєктів.

MVVM-friendly: ThemeService, NavigationService, DialogService, SnackbarService — все розроблено для DI та MVVM pattern. Легко інтегрується з сучасними архітектурами.

Обмеження: Вимагає .NET 6+, Mica тільки на Windows 11, додає ~2 MB до розміру. Для більшості проєктів це не критично.

WPF UI робить WPF додатки сучасними, професійними та приємними у використанні. Це інвестиція у user experience, яка окупається довірою користувачів та конкурентною перевагою на ринку.

Словник ключових термінів
  • WPF UI (Wpf.Ui) — open-source бібліотека Fluent контролів для WPF
  • FluentWindow — спеціальний Window з підтримкою Mica/Acrylic та rounded corners
  • NavigationView — контрол для sidebar navigation як у Windows Settings
  • CardControl — контейнер з elevation для card-based layouts
  • InfoBar — контрол для показу notifications та alerts
  • SymbolIcon — іконки з Segoe Fluent Icons шрифту
  • Mica — напівпрозорий матеріал Windows 11 з subtle texture
  • Acrylic — напівпрозорий матеріал з blur ефектом
  • ThemeService — сервіс для управління темами (Light/Dark/System)
  • NavigationService — сервіс для програмної навігації між сторінками
  • DialogService — сервіс для показу модальних діалогів
  • SnackbarService — сервіс для показу toast notifications
  • Appearance — властивість для стилізації контролів (Primary, Secondary, Danger)

Додаткові ресурси

WPF UI GitHub

Офіційний репозиторій WPF UI з вихідним кодом та issues

WPF UI Documentation

Офіційна документація з прикладами та API reference

WPF UI Gallery

Demo додаток з усіма контролами та прикладами використання

Fluent UI System Icons

Повний каталог Fluent іконок для SymbolIcon

Wpf.Ui NuGet

NuGet пакет WPF UI з версіями та release notes

WPF UI Discussions

GitHub Discussions для питань та обговорень

Попередня стаття: Fluent UI у WPF — офіційна Fluent тема від Microsoft.

Наступна стаття: XAML Namespaces та Resources — робота з просторами імен та ресурсами у XAML.