I-Synergy.Framework.UI.WPF 2026.11114.12249

Prefix Reserved
dotnet add package I-Synergy.Framework.UI.WPF --version 2026.11114.12249
                    
NuGet\Install-Package I-Synergy.Framework.UI.WPF -Version 2026.11114.12249
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="I-Synergy.Framework.UI.WPF" Version="2026.11114.12249" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="I-Synergy.Framework.UI.WPF" Version="2026.11114.12249" />
                    
Directory.Packages.props
<PackageReference Include="I-Synergy.Framework.UI.WPF" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add I-Synergy.Framework.UI.WPF --version 2026.11114.12249
                    
#r "nuget: I-Synergy.Framework.UI.WPF, 2026.11114.12249"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package I-Synergy.Framework.UI.WPF@2026.11114.12249
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=I-Synergy.Framework.UI.WPF&version=2026.11114.12249
                    
Install as a Cake Addin
#tool nuget:?package=I-Synergy.Framework.UI.WPF&version=2026.11114.12249
                    
Install as a Cake Tool

I-Synergy Framework UI WPF

Windows Presentation Foundation (WPF) UI framework for building modern desktop applications on Windows. This package provides a complete WPF implementation of the I-Synergy Framework UI services, controls, and patterns with support for Windows 7, 8, and 10+.

NuGet License .NET Platform

Features

  • Full WPF desktop support for Windows 7+, 8+, and 10+
  • Dialog service with MessageBox and custom dialog support
  • Navigation service with frame-based navigation
  • Theme service with dynamic accent colors and styles
  • File service with Windows file dialogs
  • Clipboard service for Windows clipboard operations
  • Update service for application updates
  • Custom controls (BladeView, Console, ImageBrowser, Menu, Tiles, ErrorPresenter)
  • Behaviors using Microsoft.Xaml.Behaviors.Wpf
  • 40+ dynamic theme palettes with XAML resource dictionaries
  • Splash screen support with customizable UI

Installation

Install the package via NuGet:

dotnet add package I-Synergy.Framework.UI.WPF

Quick Start

1. Configure Application

Setup your WPF application with I-Synergy Framework:

using ISynergy.Framework.UI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

public partial class App : Application
{
    private IHost _host;

    protected override async void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        _host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                // Core services
                services.AddSingleton<ILanguageService, LanguageService>();
                services.AddSingleton<IMessengerService, MessengerService>();
                services.AddSingleton<IBusyService, BusyService>();

                // WPF services
                services.AddSingleton<IDialogService, DialogService>();
                services.AddSingleton<INavigationService, NavigationService>();
                services.AddSingleton<IThemeService, ThemeService>();
                services.AddSingleton<IFileService<FileResult>, FileService>();
                services.AddSingleton<IClipboardService, ClipboardService>();
                services.AddSingleton<IUpdateService, UpdateService>();

                // ViewModels
                services.AddTransient<MainViewModel>();
                services.AddTransient<ShellViewModel>();
            })
            .Build();

        await _host.StartAsync();

        // Apply theme
        var themeService = _host.Services.GetRequiredService<IThemeService>();
        themeService.ApplyTheme();

        // Show main window
        var mainWindow = _host.Services.GetRequiredService<MainWindow>();
        mainWindow.Show();
    }

    protected override async void OnExit(ExitEventArgs e)
    {
        await _host.StopAsync();
        _host.Dispose();
        base.OnExit(e);
    }
}

2. Create XAML Windows with ViewModels

<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:MyApp.ViewModels"
        d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
        Title="{Binding Title}"
        Height="600" Width="800">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        
        <Menu Grid.Row="0">
            <MenuItem Header="File">
                <MenuItem Header="New" Command="{Binding NewCommand}"/>
                <MenuItem Header="Open" Command="{Binding OpenCommand}"/>
                <MenuItem Header="Save" Command="{Binding SaveCommand}"/>
                <Separator/>
                <MenuItem Header="Exit" Command="{Binding ExitCommand}"/>
            </MenuItem>
            <MenuItem Header="Edit">
                <MenuItem Header="Settings" Command="{Binding SettingsCommand}"/>
            </MenuItem>
        </Menu>

        
        <Frame Grid.Row="1"
               x:Name="MainFrame"
               NavigationUIVisibility="Hidden"/>

        
        <StatusBar Grid.Row="2">
            <StatusBarItem>
                <TextBlock Text="{Binding StatusMessage}"/>
            </StatusBarItem>
            <StatusBarItem HorizontalAlignment="Right">
                <ProgressBar Width="100"
                             Height="16"
                             IsIndeterminate="{Binding BusyService.IsBusy}"/>
            </StatusBarItem>
        </StatusBar>
    </Grid>
</Window>
using ISynergy.Framework.Mvvm.ViewModels;

public partial class MainWindow : Window
{
    public MainWindow(MainViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;
    }
}

3. Use Dialog Service

using ISynergy.Framework.Mvvm.ViewModels;
using ISynergy.Framework.Mvvm.Commands;

public class ProductViewModel : ViewModel
{
    private readonly IProductService _productService;

    public AsyncRelayCommand SaveCommand { get; }
    public AsyncRelayCommand DeleteCommand { get; }

    public ProductViewModel(
        ICommonServices commonServices,
        IProductService productService,
        ILogger<ProductViewModel> logger)
        : base(commonServices, logger)
    {
        _productService = productService;

        SaveCommand = new AsyncRelayCommand(SaveAsync, CanSave);
        DeleteCommand = new AsyncRelayCommand(DeleteAsync);
    }

    private bool CanSave() => !string.IsNullOrEmpty(Name) && IsValid;

    private async Task SaveAsync()
    {
        try
        {
            CommonServices.BusyService.StartBusy("Saving product...");

            await _productService.SaveAsync(Product);

            await CommonServices.DialogService.ShowInformationAsync(
                "Product saved successfully",
                "Success");
        }
        catch (Exception ex)
        {
            await CommonServices.DialogService.ShowErrorAsync(ex, "Error");
        }
        finally
        {
            CommonServices.BusyService.StopBusy();
        }
    }

    private async Task DeleteAsync()
    {
        var result = await CommonServices.DialogService.ShowMessageAsync(
            "Are you sure you want to delete this product?",
            "Confirm Delete",
            MessageBoxButtons.YesNo);

        if (result == MessageBoxResult.Yes)
        {
            try
            {
                await _productService.DeleteAsync(Product.Id);
                await CommonServices.NavigationService.GoBackAsync();
            }
            catch (Exception ex)
            {
                await CommonServices.DialogService.ShowErrorAsync(ex, "Error");
            }
        }
    }

    // Show custom dialog
    private async Task EditSettingsAsync()
    {
        await CommonServices.DialogService
            .ShowDialogAsync<SettingsWindow, SettingsViewModel, Settings>();
    }
}

4. Navigation Service

public class ShellViewModel : ViewModel
{
    private readonly INavigationService _navigationService;

    public AsyncRelayCommand<Type> NavigateCommand { get; }

    public ShellViewModel(
        ICommonServices commonServices,
        INavigationService navigationService,
        ILogger<ShellViewModel> logger)
        : base(commonServices, logger)
    {
        _navigationService = navigationService;
        NavigateCommand = new AsyncRelayCommand<Type>(NavigateAsync);
    }

    private async Task NavigateAsync(Type viewModelType)
    {
        await _navigationService.NavigateAsync(viewModelType);
    }

    // Navigate with parameters
    private async Task NavigateToProductDetailAsync(Product product)
    {
        await _navigationService.NavigateAsync<ProductDetailViewModel>(product);
    }

    // Navigate back
    private async Task GoBackAsync()
    {
        if (_navigationService.CanGoBack)
        {
            await _navigationService.GoBackAsync();
        }
    }
}

5. File Operations

using ISynergy.Framework.Mvvm.Abstractions.Services;
using ISynergy.Framework.Core.Models.Results;

public class DocumentViewModel : ViewModel
{
    private readonly IFileService<FileResult> _fileService;

    public AsyncRelayCommand OpenFileCommand { get; }
    public AsyncRelayCommand SaveFileCommand { get; }

    public DocumentViewModel(
        ICommonServices commonServices,
        IFileService<FileResult> fileService,
        ILogger<DocumentViewModel> logger)
        : base(commonServices, logger)
    {
        _fileService = fileService;

        OpenFileCommand = new AsyncRelayCommand(OpenFileAsync);
        SaveFileCommand = new AsyncRelayCommand(SaveFileAsync);
    }

    private async Task OpenFileAsync()
    {
        var file = await _fileService.BrowseFileAsync(
            new[] { ".pdf", ".docx", ".txt" });

        if (file is not null)
        {
            // Read file content
            using var stream = await file.OpenReadAsync();
            // Process file...
        }
    }

    private async Task SaveFileAsync()
    {
        var file = await _fileService.SaveFileAsync(
            "document.pdf",
            "Documents",
            new[] { ".pdf" });

        if (file is not null)
        {
            // Write file content
            using var stream = await file.OpenWriteAsync();
            // Save content...
        }
    }
}

6. Update Service

using ISynergy.Framework.Mvvm.Abstractions.Services;

public class UpdateViewModel : ViewModel
{
    private readonly IUpdateService _updateService;

    public AsyncRelayCommand CheckForUpdatesCommand { get; }
    public AsyncRelayCommand InstallUpdateCommand { get; }

    public bool UpdateAvailable
    {
        get => GetValue<bool>();
        set => SetValue(value);
    }

    public string UpdateVersion
    {
        get => GetValue<string>();
        set => SetValue(value);
    }

    public UpdateViewModel(
        ICommonServices commonServices,
        IUpdateService updateService,
        ILogger<UpdateViewModel> logger)
        : base(commonServices, logger)
    {
        _updateService = updateService;

        CheckForUpdatesCommand = new AsyncRelayCommand(CheckForUpdatesAsync);
        InstallUpdateCommand = new AsyncRelayCommand(InstallUpdateAsync);
    }

    private async Task CheckForUpdatesAsync()
    {
        try
        {
            var update = await _updateService.CheckForUpdateAsync();

            if (update.IsAvailable)
            {
                UpdateAvailable = true;
                UpdateVersion = update.Version;

                var result = await CommonServices.DialogService.ShowMessageAsync(
                    $"A new version ({update.Version}) is available. Would you like to install it?",
                    "Update Available",
                    MessageBoxButtons.YesNo);

                if (result == MessageBoxResult.Yes)
                {
                    await InstallUpdateAsync();
                }
            }
            else
            {
                await CommonServices.DialogService.ShowInformationAsync(
                    "You are running the latest version.",
                    "No Updates");
            }
        }
        catch (Exception ex)
        {
            await CommonServices.DialogService.ShowErrorAsync(ex, "Error");
        }
    }

    private async Task InstallUpdateAsync()
    {
        try
        {
            CommonServices.BusyService.StartBusy("Downloading update...");

            await _updateService.DownloadAndInstallUpdateAsync(
                progress => CommonServices.BusyService.UpdateMessage($"Downloading... {progress}%"));

            await CommonServices.DialogService.ShowInformationAsync(
                "Update installed successfully. The application will now restart.",
                "Update Complete");

            _updateService.RestartApplication();
        }
        catch (Exception ex)
        {
            await CommonServices.DialogService.ShowErrorAsync(ex, "Error");
        }
        finally
        {
            CommonServices.BusyService.StopBusy();
        }
    }
}

Custom Controls

BladeView

<controls:BladeView ItemsSource="{Binding Blades}"
                    Anchor="Auto"
                    BladeMaxWidth="520" />

See Blades (edge panes) for the blade contract and the right-to-left rule.

ImageBrowser

<controls:ImageBrowser Images="{Binding ProductImages}"
                       SelectedImage="{Binding SelectedImage}"
                       AllowAdd="True"
                       AllowRemove="True" />

Console

<controls:Console Messages="{Binding ConsoleMessages}"
                  AutoScroll="True" />

ErrorPresenter

<controls:ErrorPresenter Errors="{Binding ValidationErrors}"
                         Visibility="{Binding HasErrors, Converter={StaticResource BoolToVisibilityConverter}}" />

Tiles

<controls:Tile Title="Dashboard"
               Command="{Binding NavigateToDashboardCommand}"
               Icon="{StaticResource DashboardIcon}" />

6. Live Localization with IndexerBinding

Bind directly to LocalizedStrings.Default indexer for automatic language switching without page reload:

<Window xmlns:local="clr-namespace:ISynergy.Framework.Globalization.Services;assembly=ISynergy.Framework.Globalization"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    
    <TextBlock Text="{Binding [WelcomeMessage], Source={x:Static local:LocalizedStrings.Default}}" />
    
    <Label Content="{Binding [GreetingText], Source={x:Static local:LocalizedStrings.Default}}" />
</Window>

When the application language changes, simply call:

var newCulture = new CultureInfo("fr-FR");
newCulture.ApplyCulture();  // Triggers PropertyChanged("Item[]") on LocalizedStrings.Default

All bound controls automatically update with the new translations — no page refresh needed.

Blades (edge panes)

A blade is a card that slides in from a screen edge and stacks on top of the previous one, matching the WinUI BladeView interaction. The owning view model implements IViewModelBladeView and exposes the stack through Blades (ObservableCollection<IView>) plus IsPaneVisible. Blades are opened through IBladeService.OpenBladeAsync<TBladeViewModel, TEntity>(owner, ...), which resolves the view and view model from a DI scope, appends the view to owner.Blades and disables every earlier blade; closing the newest blade removes it and re-enables the previous one. Derive the owner from ViewModelBladeView<TModel> to get Blades and the blade commands for free.

Host the pane in the owning view:

<controls:BladeView ItemsSource="{Binding Blades}"
                    Anchor="Start" />

BladeView properties:

  • ItemsSource — the blade views to host, in opening order. When null, the Blades of the IViewModelBladeView data context is used.
  • Anchor — the logical edge, Auto (default, resolves to End), Start or End.
  • DisabledOpacity — opacity of every blade except the newest one (0.75 by default).
  • BladeSpacing — gap between two adjacent blades (10 by default).
  • BladeMaxWidth — maximum width of a single blade card (520 by default).
  • InnerPadding — padding between the blade stack and the host edges (8 on every side by default).

The pane collapses itself when there is no blade or when the owner sets IsPaneVisible to false, clicking the scrim closes the newest blade through its CloseCommand, and the newest blade is the only interactive one.

Shell-level pane

Controls/BladeHostView is a self-contained host: it resolves the framework's BladeHostViewModel (ISynergy.Framework.UI/ViewModels, registered as a singleton) from Application.Services, sets it as its own DataContext, and hosts a BladeView bound to Blades. Because the owner belongs to the shell rather than to a page, the pane survives page navigation and a blade opened from anywhere docks into the same stack. When the view model cannot be resolved (design time, or a host that does not register it) the control stays collapsed and traces the failure instead of throwing.

<c:BladeHostView Grid.RowSpan="2" Grid.ColumnSpan="3" />

Use BladeHostView when the blades are shell-level, and a page-level BladeView when the blades belong to a page — there ItemsSource="{Binding Blades}" binds to that page's own IViewModelBladeView. The sample's Settings is opened this way: ShellViewModel.OpenSettingsAsync calls _bladeService.OpenBladeAsync<SettingsViewModel, object>(_bladeHost) and ShellView hosts BladeHostView above the content frame, below the busy overlay.

Right-to-left

Anchor is logical: Start is the left edge in a left-to-right culture and the right edge in a right-to-left one, and Auto follows End. The edge is resolved once through BladePlacement.IsStartSide/BladePlacement.HorizontalSign, never hardcoded. The positioning container under the pane is deliberately forced to LeftToRight so Left/Right alignment stay physical, while each blade's Frame receives the ambient FlowDirection so the blade content mirrors; the slide-in direction uses HorizontalSign, because WPF never mirrors render transforms. The pane re-resolves both on FlowDirectionChanged.

A blade view must derive from c:View — a WPF Page — because BladeView hosts it in a Frame (JournalOwnership = OwnsJournal, navigation UI hidden); any other element is rejected with a trace error instead of being added.

Theme Support

The WPF framework includes 40+ built-in theme palettes:

using ISynergy.Framework.Mvvm.Abstractions.Services;

// Theme is automatically applied on startup
// To change theme programmatically:
public void ChangeTheme(string colorHex, Themes theme)
{
    // Update settings
    _settingsService.LocalSettings.Color = colorHex;
    _settingsService.LocalSettings.Theme = theme;

    // Apply theme
    _themeService.ApplyTheme();

    // Restart application to fully apply theme
    System.Windows.Forms.Application.Restart();
    System.Windows.Application.Current.Shutdown();
}

// Light/dark switching is built into the shell: ThemeCommand toggles through IThemeService.
// Language, theme and accent color are selected in your own settings page.

Behaviors

Using Microsoft.Xaml.Behaviors.Wpf:

<Window xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
    <i:Interaction.Behaviors>
        <behaviors:WindowDragBehavior />
    </i:Interaction.Behaviors>

    <TextBox>
        <i:Interaction.Behaviors>
            <behaviors:SelectAllOnFocusBehavior />
        </i:Interaction.Behaviors>
    </TextBox>
</Window>

Best Practices

Use Frame for navigation between pages and Window for dialogs and child windows.

Always configure theme on application startup for consistent UI appearance.

WPF supports Windows 7, 8, and 10+ through different target frameworks.

Application Structure

  • Use MVVM pattern with dependency injection
  • Configure services in Host builder
  • Apply theme on startup
  • Use NavigationService for page navigation
  • Handle application updates gracefully

Performance

  • Use virtualization for large lists
  • Implement lazy loading for complex views
  • Dispose resources properly
  • Use compiled bindings where possible
  • Leverage hardware acceleration

Dependencies

  • I-Synergy.Framework.UI - Base UI abstractions
  • Microsoft.Xaml.Behaviors.Wpf - WPF behaviors
  • Microsoft.Extensions.Configuration.Json - Configuration
  • Microsoft.Extensions.Hosting - Application hosting
  • OpenTelemetry.Instrumentation.Http - HTTP telemetry
  • OpenTelemetry.Instrumentation.Runtime - Runtime telemetry

Platform Requirements

  • Windows 7.0: .NET 10.0-windows7.0
  • Windows 8.0: .NET 10.0-windows8.0
  • Windows 10+: .NET 10.0-windows10.0.26100.0

Documentation

  • I-Synergy.Framework.UI - Base UI abstractions
  • I-Synergy.Framework.Core - Core framework
  • I-Synergy.Framework.Mvvm - MVVM framework
  • I-Synergy.Framework.UI.WinUI - WinUI implementation
  • I-Synergy.Framework.UI.Maui - MAUI implementation

Support

For issues, questions, or contributions, please visit the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible.  net10.0-windows8.0 is compatible.  net10.0-windows10.0.26100 is compatible.  net11.0-windows7.0 is compatible.  net11.0-windows8.0 is compatible.  net11.0-windows10.0.26100 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.11114.12249 53 11/14/2026
2026.11114.11807-preview 40 11/14/2026
2026.11114.11740-preview 44 11/14/2026
2026.11114.11330 53 11/14/2026
2026.11114.11302-preview 65 11/14/2026
2026.11112.10146 80 11/12/2026
2026.11112.10114-preview 77 11/12/2026
2026.11111.12233 81 11/12/2026
2026.11111.12212-preview 67 11/11/2026
2026.11111.12142-preview 72 11/11/2026
2026.11111.11259-preview 68 11/11/2026
2026.11111.11219-preview 70 11/11/2026
2026.11111.10206 76 11/11/2026
2026.11111.10127-preview 85 11/11/2026
2026.11110.12025-preview 46 11/10/2026
2026.11110.12000-preview 52 11/10/2026
2026.11110.11608-preview 53 11/10/2026
2026.11110.11539-preview 51 11/10/2026
2026.11110.11423-preview 55 11/10/2026
2026.11027.11355 62 11/11/2026
Loading failed