Skip to content

Installation

Navius.Wpf ships as four packages, all targeting net8.0-windows and net10.0-windows and all declaring an explicit package id and version, plus full package metadata (SourceLink, snupkg symbols, a package README, and package validation).

Package Version Project references Other dependencies
Navius.Wpf.Primitives 1.0.0-preview.8 none none
Navius.Wpf.Ui 1.0.0-preview.8 Navius.Wpf.Primitives none
Navius.Wpf.Motion 1.0.0-preview.4 none none
Navius.Wpf.Charts 1.0.0-preview.4 Navius.Wpf.Primitives LiveChartsCore.SkiaSharpView.WPF 2.0.5; System.IO.Ports 8.0.0

All four packages are published on NuGet.org. Add whichever ones a project needs:

dotnet add package Navius.Wpf.Primitives --version 1.0.0-preview.8
dotnet add package Navius.Wpf.Ui --version 1.0.0-preview.8
dotnet add package Navius.Wpf.Motion --version 1.0.0-preview.4
dotnet add package Navius.Wpf.Charts --version 1.0.0-preview.4

Navius.Wpf.Ui and Navius.Wpf.Charts both carry a project reference to Navius.Wpf.Primitives, so a project that only needs styled components or charts does not need to add Navius.Wpf.Primitives on its own; NuGet resolves it transitively. The transitive version is the Primitives version current when the referencing package was packed (Ui 1.0.0-preview.8 resolves Primitives 1.0.0-preview.8), so a project that needs a newer Primitives release than its Ui package floors at must reference Navius.Wpf.Primitives directly.

Navius.Wpf also ships a copy-paste component registry, navius-wpf (package id navius-wpf, version 1.0.0-preview.7, packed with PackAsTool). Install it globally, then run it as the bare navius-wpf command:

dotnet tool install --global navius-wpf --version 1.0.0-preview.7
navius-wpf <command>

The registry at registry/registry.json and a copy of the Navius.Wpf.Primitives and Navius.Wpf.Ui source trees are bundled into the tool package under registry-source/, so add and registry-sync work with no local repo checkout.

Contributors working from a Navius.Wpf clone can run the CLI project directly instead:

dotnet run --project tools/Navius.Wpf.Cli -- <command>

The command surface, as implemented in tools/Navius.Wpf.Cli/Program.cs:

navius-wpf list [--registry <path>]
navius-wpf add <name> --to <dir> --namespace <ns> [--root <repo>] [--registry <path>]
navius-wpf registry-sync [--root <repo>] [--registry <path>]
  • list prints every registry item’s name, type, file count, and registryDependencies.
  • add <name> is the vendoring command a consumer runs. --to <dir> and --namespace <ns> are required. --root <repo> points source-path resolution at a specific repo checkout instead of the current directory; --registry <path> points at a specific registry.json instead of the one resolved automatically (working-directory copy first, then the bundled copy next to the tool’s own assembly).
  • registry-sync regenerates registry/registry.json by rescanning src/Navius.Wpf.Primitives and src/Navius.Wpf.Ui. This is a maintainer command for the Navius.Wpf repo itself (the registry is generated, never hand-edited), not something a consuming project runs.

The CLI validates its full operation before writing. Unknown or valueless options, invalid CLR namespaces, absolute or root-escaping source/target paths, duplicate target paths, and incomplete registry closures fail with no files copied. Registry input can therefore be supplied explicitly without allowing ../ entries to escape either the source root or the consumer’s --to directory.

registry/schema.json constrains type to registry:core, registry:primitive, or registry:styled. In practice:

  • registry:core is a single item, named core: the shared overlay, positioning, and theming base layer (Overlays/, Positioning/, Theming/, Controls/Internal/, plus the OverlayBackdrop.xaml, Tokens.Light.xaml, Tokens.Dark.xaml, and Tokens.HighContrast.xaml theme dictionaries).
  • registry:primitive items map to a Navius.Wpf.Primitives control family (one folder under Controls/, or a flat Tier-A file like NaviusButton).
  • registry:styled items map to a Navius.Wpf.Ui component.

Navius.Wpf.Charts is not in the registry: registry-sync explicitly notes it as “found but intentionally excluded” and does not register any registry:chart type (the schema does not define one). Charts is only consumable as a package or project reference, not through add.

Each item’s files array lists path (a repo-root-relative source path), type (registry:code or registry:theme), and target (the path under the consumer’s --to directory).

An item’s registryDependencies names other item ids its source references. add resolves this set transitively and topologically (dependencies copied before the item that needs them) before copying anything, so vendoring select also brings in anchored-popup and core, the exact composite case this closure step exists for: a registry item vendored without its full dependency closure left dangling types that did not compile, a defect class first found while hardening the sibling web CLI. tests/Navius.Wpf.Cli.Tests/VendoringClosureTests.cs is the gate: it shells the real add command against a temp WPF classlib project, then runs dotnet build on the result, for both a no-dependency item (button) and the select composite case.

Two text rewrites run on every copied file, in this order:

  1. Theme pack-URI fix: a XAML file with pack://application:,,,/Navius.Wpf.Primitives;component/Themes/X.xaml (or the shorthand /Navius.Wpf.Primitives;component/Themes/X.xaml) has that authority segment stripped to a bare X.xaml, since vendored source has no compiled assembly for the pack URI to resolve against; theme dictionaries land as plain files next to each other. The Navius.Wpf.Ui equivalent is rewritten to Ui.X.xaml instead, since Ui-origin and Primitives-origin theme dictionaries land in the same flattened NaviusWpf/Themes/ folder and would otherwise collide by name.
  2. Namespace rewrite: every occurrence of Navius.Wpf.Primitives in the file text becomes <namespace>.NaviusWpf.Primitives, and every occurrence of Navius.Wpf.Ui becomes <namespace>.NaviusWpf.Ui, where <namespace> is the --namespace value. This is a plain text replace, so it also rewrites xmlns:controls="clr-namespace:Navius.Wpf.Primitives.Controls" style strings inside XAML, not just C# namespace declarations.

With the global tool installed:

navius-wpf add select --to . --namespace MyApp

From a Navius.Wpf clone, the equivalent contributor command is:

dotnet run --project tools/Navius.Wpf.Cli -- add select --to . --namespace MyApp

select’s registryDependencies are ["anchored-popup", "core"], and anchored-popup itself depends on core, so the resolved, deps-first copy order is core, anchored-popup, select. With --to . and --namespace MyApp, the files land at:

NaviusWpf/Primitives/Controls/Internal/LogicalTreeWalker.cs (core)
NaviusWpf/Primitives/Controls/Internal/PanelHeightAnimator.cs (core)
NaviusWpf/Primitives/Controls/Internal/SegmentEngine.cs (core)
NaviusWpf/Primitives/Controls/Internal/TimePickerOptions.cs (core)
NaviusWpf/Primitives/Controls/Internal/VisualAncestorWalker.cs (core)
NaviusWpf/Primitives/Overlays/OverlayBackdrop.cs (core)
NaviusWpf/Primitives/Overlays/OverlayCloseReason.cs (core)
NaviusWpf/Primitives/Overlays/OverlayClosingEventArgs.cs (core)
NaviusWpf/Primitives/Overlays/OverlayDismissPolicy.cs (core)
NaviusWpf/Primitives/Overlays/OverlayOptions.cs (core)
NaviusWpf/Primitives/Overlays/OverlaySession.cs (core)
NaviusWpf/Primitives/Overlays/OverlayStack.cs (core)
NaviusWpf/Primitives/Positioning/AnchoredPlacementOptions.cs (core)
NaviusWpf/Primitives/Positioning/MonitorWorkArea.cs (core)
NaviusWpf/Primitives/Positioning/PlacementAlign.cs (core)
NaviusWpf/Primitives/Positioning/PlacementMath.cs (core)
NaviusWpf/Primitives/Positioning/PlacementResult.cs (core)
NaviusWpf/Primitives/Positioning/PlacementSide.cs (core)
NaviusWpf/Primitives/Theming/NaviusTheme.cs (core)
NaviusWpf/Primitives/Theming/ThemeManager.cs (core)
NaviusWpf/Themes/OverlayBackdrop.xaml (core)
NaviusWpf/Themes/Tokens.Dark.xaml (core)
NaviusWpf/Themes/Tokens.HighContrast.xaml (core)
NaviusWpf/Themes/Tokens.Light.xaml (core)
NaviusWpf/Primitives/Controls/NaviusAnchoredPopup.cs (anchored-popup)
NaviusWpf/Primitives/Controls/Select/NaviusSelect.cs (select)
NaviusWpf/Primitives/Controls/Select/NaviusSelectBase.cs (select)
NaviusWpf/Primitives/Controls/Select/NaviusSelectEventArgs.cs (select)
NaviusWpf/Primitives/Controls/Select/NaviusSelectItem.cs (select)
NaviusWpf/Primitives/Controls/Select/SelectSelectionEngine.cs (select)
NaviusWpf/Themes/Select.xaml (select)

Every .cs and .xaml file in that set has Navius.Wpf.Primitives rewritten to MyApp.NaviusWpf.Primitives (this closure has no Navius.Wpf.Ui-origin file, so no Ui.-prefixed theme file or Ui namespace rewrite occurs here).

The Gallery app (apps/Navius.Wpf.Gallery) shows the minimum wiring a consuming app needs, whether it references the packages or vendors via the CLI.

App.xaml declares an empty <Application.Resources>; it does not merge any control theme dictionary by hand. That works because both Navius.Wpf.Primitives and Navius.Wpf.Ui carry [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)], so WPF’s own default-style resolution locates each assembly’s Themes/Generic.xaml automatically; no explicit merge is needed for control templates and default styles.

The one thing that does need runtime wiring is the token dictionary, since controls read Navius.* tokens through DynamicResource, and a DynamicResource lookup needs that dictionary present somewhere in the live resource chain. App.xaml.cs supplies it in OnStartup:

using System.Windows;
using Navius.Wpf.Primitives.Theming;
namespace MyApp;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ThemeManager.Apply(NaviusTheme.Light);
}
}

ThemeManager.Apply(NaviusTheme.Light) injects Themes/Tokens.Light.xaml into Application.Current.Resources.MergedDictionaries, which is enough for every consumer of the tokens (package reference or vendored) to resolve DynamicResource Navius.* lookups. A vendored project calls the same method from its rewritten namespace (e.g. MyApp.NaviusWpf.Primitives.Theming.ThemeManager.Apply(...)), since the CLI’s namespace rewrite applies to the vendored ThemeManager.cs and NaviusTheme.cs exactly as it does to any other vendored file.