Installation
Packages
Section titled “Packages”Navius.Wpf ships as four packages. Three target net8.0-windows and net10.0-windows and declare an explicit package id and version; Navius.Wpf.Charts targets the same two frameworks but declares neither.
| Package | Version | Project references | Other dependencies |
|---|---|---|---|
Navius.Wpf.Primitives |
1.0.0-preview.1 |
none | none |
Navius.Wpf.Ui |
1.0.0-preview.1 |
Navius.Wpf.Primitives |
none |
Navius.Wpf.Motion |
1.0.0-preview.1 |
none | none |
Navius.Wpf.Charts |
not pinned (see below) | Navius.Wpf.Primitives |
LiveChartsCore.SkiaSharpView.WPF 2.0.5 |
The library ships as NuGet packages at 1.0.0-preview.1. Navius.Wpf.Charts’s csproj sets no
PackageId or Version property, unlike the other three, so packing it falls back to the .NET
SDK’s own defaults (the project name as the package id, 1.0.0 as the version) rather than the
1.0.0-preview.1 the other three declare explicitly.
Add whichever packages a project needs:
dotnet add package Navius.Wpf.Primitives --version 1.0.0-preview.1dotnet add package Navius.Wpf.Ui --version 1.0.0-preview.1dotnet add package Navius.Wpf.Motion --version 1.0.0-preview.1dotnet add package Navius.Wpf.ChartsNavius.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.
Vendoring with the CLI
Section titled “Vendoring with the CLI”Navius.Wpf also ships a copy-paste component registry, navius-wpf (package id navius-wpf,
version 1.0.0-preview.1, packed with PackAsTool so it installs and runs as a dotnet tool).
The registry lives at registry/registry.json in the source repo and is bundled into the tool
package itself, alongside a copy of the Navius.Wpf.Primitives and Navius.Wpf.Ui source trees
under registry-source/, so add and registry-sync still work when the tool is installed
globally with no local repo checkout.
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>]listprints every registry item’s name, type, file count, andregistryDependencies.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 specificregistry.jsoninstead of the one resolved automatically (working-directory copy first, then the bundled copy next to the tool’s own assembly).registry-syncregeneratesregistry/registry.jsonby rescanningsrc/Navius.Wpf.Primitivesandsrc/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.
Registry item types
Section titled “Registry item types”registry/schema.json constrains type to registry:core, registry:primitive, or
registry:styled. In practice:
registry:coreis a single item, namedcore: the shared overlay, positioning, and theming base layer (Overlays/,Positioning/,Theming/,Controls/Internal/, plus theOverlayBackdrop.xaml,Tokens.Light.xaml, andTokens.Dark.xamltheme dictionaries).registry:primitiveitems map to aNavius.Wpf.Primitivescontrol family (one folder underControls/, or a flat Tier-A file likeNaviusButton).registry:styleditems map to aNavius.Wpf.Uicomponent.
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).
Dependency closure
Section titled “Dependency closure”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:
- 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 bareX.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. TheNavius.Wpf.Uiequivalent is rewritten toUi.X.xamlinstead, since Ui-origin and Primitives-origin theme dictionaries land in the same flattenedNaviusWpf/Themes/folder and would otherwise collide by name. - Namespace rewrite: every occurrence of
Navius.Wpf.Primitivesin the file text becomes<namespace>.NaviusWpf.Primitives, and every occurrence ofNavius.Wpf.Uibecomes<namespace>.NaviusWpf.Ui, where<namespace>is the--namespacevalue. This is a plain text replace, so it also rewritesxmlns:controls="clr-namespace:Navius.Wpf.Primitives.Controls"style strings inside XAML, not just C#namespacedeclarations.
Worked example: vendoring select
Section titled “Worked example: vendoring select”navius-wpf add select --to . --namespace MyAppselect’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.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).
App wiring
Section titled “App wiring”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.