Compass.Wpf 0.0.15

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Compass.Wpf --version 0.0.15
                    
NuGet\Install-Package Compass.Wpf -Version 0.0.15
                    
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="Compass.Wpf" Version="0.0.15" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Compass.Wpf" Version="0.0.15" />
                    
Directory.Packages.props
<PackageReference Include="Compass.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 Compass.Wpf --version 0.0.15
                    
#r "nuget: Compass.Wpf, 0.0.15"
                    
#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 Compass.Wpf@0.0.15
                    
#: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=Compass.Wpf&version=0.0.15
                    
Install as a Cake Addin
#tool nuget:?package=Compass.Wpf&version=0.0.15
                    
Install as a Cake Tool

Compass

The Source Generator Powered UI Infrastructure for Avalonia & WPF

Compass is a comprehensive Application Infrastructure designed to streamline the development of modern, type-safe desktop applications. By leveraging C# Source Generators, Compass eliminates runtime reflection overhead while providing a developer experience similar to ASP.NET Core or Blazor.

It is not just a routerβ€”it is a complete solution for Navigation, Dialogs, Notifications, Authorization, and Dependency Injection.

✨ Key Features

  • πŸš€ Type-Safe Navigation: Zero runtime reflection. Routes are strongly-typed C# records with constructor injection for parameters.
  • πŸ’¬ Unified Interaction Service: Built-in support for Dialogs, Toasts, and Snackbars, managed via a clean, testable service API.
  • πŸ›‘οΈ Integrated Security: Policy-based authorization (Roles, Policies, Claims) deeply integrated into navigation and UI components (AuthorizeView).
  • 🧩 Advanced Layouts: Declarative, nested layouts (e.g., MainLayout -> SettingsLayout -> Page) defined directly in Route attributes.
  • 🧠 Intelligent Auto-Wiring: Automatically locates and injects ViewModels based on conventions or explicit configuration.
  • ⚑ Async Lifecycle: Robust lifecycle management (IPreloadable, INavigatingFrom) for async data loading and navigation guards.
  • πŸ› οΈ Dependency Injection: Seamless integration with Microsoft.Extensions.DependencyInjection.
  • πŸ”Œ Cross-Platform: Identical API for Avalonia and WPF.

πŸš€ Getting Started

1. Installation & Resources

First, add the Compass package to your project. Then, you MUST register the theme resources in your App file.

Avalonia (App.axaml)
<Application ...>
    <Application.Styles>
        <FluentTheme />
        
        <StyleInclude Source="avares://Compass.Avalonia/Themes/CompassTheme.axaml" />
    </Application.Styles>
</Application>
WPF (App.xaml)
<Application ...>
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml" />
                
                <ResourceDictionary Source="pack://application:,,,/Compass.Wpf;component/Themes/Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

2. Service Registration

Register Compass in your App.axaml.cs (Avalonia) or App.xaml.cs (WPF):

public void ConfigureServices(IServiceCollection services)
{
    // Register Compass and its source-generated services
    services.AddCompassCore<ViewFactory>(options =>
    {
        // 1. Configure Navigation
        options.Navigation.StartRoute = new LoginRoute();

        // 2. Configure Authorization (Optional)
        options.Auth.AddPolicy("AdminOnly", p => p.RequireRole("Admin"));

        // 3. Configure Interaction Defaults (Optional)
        options.Snackbars.DefaultDuration = TimeSpan.FromSeconds(3);
    });
}

3. Define the View Factory

Create a partial class marked with [ViewFactory]. The source generator will implement the resolution logic here. This file can be empty.

using Compass;

namespace MyApp.Services;

[ViewFactory]
public partial class ViewFactory;

4. Setup the Shell (UI)

In your MainWindow, use the CompassShell control. This acts as the host for pages, dialogs, and notifications.

Avalonia (MainWindow.axaml):

<Window xmlns:nav="using:Compass" ...>
    
    <nav:CompassShell ShellContent="{Binding ShellContent}" />
</Window>

ViewModel (MainViewModel.cs):

public class MainViewModel(IShellContent shellContent) : ViewModelBase
{
    public IShellContent ShellContent { get; } = shellContent;
}

🧭 Core Concepts

1. Navigation & Routes

Routes are defined as partial records. Compass uses these records to match Views and ViewModels.

// Simple Route (Maps to HomePage + HomePageViewModel)
[Route<HomePage>]
public partial record HomeRoute;

// Route with Parameters & Layout
[Route<ProductPage, MainLayout>]
public partial record ProductRoute(int ProductId, string Mode);

Using INavigationService:

Method Description
NavigateAsync(route) Pushes a new instance of the page onto the stack.
GoToAsync(route) Smart navigation. If an equivalent route (by record equality) exists in the stack, it brings it to the top. Otherwise, behaves like NavigateAsync.
GoBackAsync() Pops the current page.
Post(mode, route) Safely schedules navigation on the UI thread. Use this inside lifecycle methods to avoid deadlocks.
public class HomeViewModel(INavigationService nav) : ViewModelBase
{
    public async Task OpenProduct()
    {
        // Type-safe parameters!
        await nav.GoToAsync(new ProductRoute(42, "Edit"));
    }
}

2. Interaction (Dialogs, Toasts, Snackbars)

Compass provides a unified API for UI interactions, decoupling your ViewModels from View implementation details.

Dialogs (IDialogService):

// 1. Define Args
public record ConfirmArgs(string Title, string Message) : IDialogArgs<bool>;

// 2. Call Service
public class MyViewModel(IDialogService dialogs)
{
    public async Task DeleteItem()
    {
        // Simple usage
        var confirmed = await dialogs.ShowDialogAsync(new ConfirmArgs("Delete?", "Are you sure?"));

        // Advanced usage (Builder)
        var result = await dialogs.Make(new ConfirmArgs("Delete?", "Sure?"))
            .SetCloseOnOverlayClick(false)
            .SetModal(true)
            .ShowAsync();
    }
}

Snackbars & Toasts:

public class MyViewModel(ISnackbarService snackbars, IToastService toasts)
{
    public void Save()
    {
        // Snackbar with Action
        snackbars.Show("File Saved", "Undo", () => UndoSave());

        // Simple Toast
        toasts.Show("Operation Successful", type: ToastType.Success);
    }
}

3. Lifecycle Management

Implement interfaces on your ViewModel to hook into navigation events.

Interface Method Purpose
IPreloadable PreloadAsync Load data on a background thread before navigation completes. Runs parallel to exit animation.
INavigatedTo<T> OnNavigatedToAsync Main entry point. Access the typed Route instance here. Runs on UI thread.
INavigatingFrom OnNavigatingFromAsync Guard navigation (e.g., "Unsaved Changes"). Return false to cancel.
IReleaseAware OnReleased Cleanup resources when the ViewModel is removed from memory.

Async Data Loading Pattern:

public partial class ProductViewModel : ViewModelBase,
    IPreloadable,
    INavigatedTo<ProductRoute>
{
    private ProductData _data;

    // 1. Runs in background
    public async Task PreloadAsync(IRoute route, NavigationMode mode, CancellationToken token)
    {
        var id = ((ProductRoute)route).ProductId;
        _data = await _service.LoadProductAsync(id, token);
    }

    // 2. Runs on UI Thread after Preload completes
    public Task OnNavigatedToAsync(ProductRoute route, Task preload, NavigationMode mode)
    {
        // Update Properties (No flickering!)
        Title = _data.Name;
        return Task.CompletedTask;
    }
}

4. Authorization

Protect your routes and UI elements using the [Authorize] attribute and policies.

Configuration:

options.Auth.AddPolicy("CanDelete", p => p.RequireClaim("Permission", "Delete"));

Protecting a Route:

[Route<AdminPage>]
[Authorize(Policy = "CanDelete")]
public partial record AdminRoute;

Protecting UI (AuthorizeView):

<nav:AuthorizeView Policy="CanDelete">
    <nav:AuthorizeView.Authorized>
        <Button Command="{Binding DeleteCommand}">Delete</Button>
    </nav:AuthorizeView.Authorized>
    <nav:AuthorizeView.NotAuthorized>
        <TextBlock Text="You do not have permission to delete."/>
    </nav:AuthorizeView.NotAuthorized>
</nav:AuthorizeView>

5. Layouts

Layouts are wrapper controls (like MasterPage) that persist across page navigations. They must implement IMountableControl.

public partial class MainLayout : UserControl, IMountableControl
{
    // Tell Compass where to inject the child view
    public Control GetMountPoint() => this.FindControl<ContentControl>("Body");
}

Nested Layouts:

// Layout stack: MainLayout -> SettingsLayout -> AccountPage
[Route<AccountPage, MainLayout, SettingsLayout>]
public partial record AccountRoute;

πŸ† Best Practices

  1. Use Records for Routes: Always use partial record for routes. They provide value equality by default, which Compass uses for smart navigation (GoToAsync).
  2. Keep ViewModels Agnostic: Never reference UI controls (like Window or MessageBox) in your ViewModels. Use IDialogService and INavigationService.
  3. Async All The Way: Prefer NavigateAsync and PreloadAsync for data fetching. Avoid blocking the UI thread in constructors.
  4. Feature Folders: Organize your code by feature (e.g., Features/Products/) keeping Views, ViewModels, and Routes together.
  5. Centralized Layouts: Use Layouts (IMountableControl) for shared UI structure (NavBars, Headers) instead of repeating XAML in every page.
Product Compatible and additional computed target framework versions.
.NET net8.0-windows7.0 is compatible.  net9.0-windows was computed.  net9.0-windows7.0 is compatible.  net10.0-windows was computed.  net10.0-windows7.0 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