LiteObservableRegions 1.2.2
dotnet add package LiteObservableRegions --version 1.2.2
NuGet\Install-Package LiteObservableRegions -Version 1.2.2
<PackageReference Include="LiteObservableRegions" Version="1.2.2" />
<PackageVersion Include="LiteObservableRegions" Version="1.2.2" />
<PackageReference Include="LiteObservableRegions" />
paket add LiteObservableRegions --version 1.2.2
#r "nuget: LiteObservableRegions, 1.2.2"
#:package LiteObservableRegions@1.2.2
#addin nuget:?package=LiteObservableRegions&version=1.2.2
#tool nuget:?package=LiteObservableRegions&version=1.2.2
LiteObservableRegions
A lightweight, Prism-like region and navigation library for WPF. Define regions in XAML, navigate by URI, and resolve views from Microsoft.Extensions.DependencyInjection or from named host children.
Features
- XAML-first regions — Attached properties
ObservableRegion.RegionNameandObservableRegion.ViewNameon anyDependencyObject. The element withRegionNameis the region host (content is displayed here);ViewNameis set on a child of that host to register a named view. - URI-based navigation — Format
region://RegionName/TargetName?query. Navigate (push), Redirect (replace and clear back stack), GoBack, GoForward per region. Region names are compared case-insensitively. - Two ways to resolve views
- Named views — Set
ViewName="region://RegionName/TargetName"on a child of the host; that element is used when navigating to that target (no DI). The host must already be registered (e.g. parent hasRegionName); region name inViewNamemust match the host’s region name (case-insensitive). - DI views — Register with
AddObservableRegions(reg => reg.AddView<T>("TargetName", lifetime))orAddRegionViews(...); views are resolved from the service provider (Transient, Scoped per region, Singleton). Scoped creates one scope per region; Singleton is cached per region+target.
- Named views — Set
- Navigation stack — Per-region back and forward stacks. Redirect clears the back stack and does not push. Navigate to the same URI as current is a no-op (no stack or content change).
- INavigationAware — Optional: implement on the view or on the view’s
DataContext.OnNavigatedFrom(NavigationContext)andOnNavigatedTo(NavigationContext)receive FromUri, ToUri, Parameters, Mode, RegionName, TargetName;context.IsRedirectfor Redirect. - Pluggable host adapter —
IRegionHostContentAdapter.SetContent(host, content). Register beforeAddObservableRegionsto customize. Default: ContentControl→Content, Frame→Navigate(content), Panel/ItemsControl→add child and toggle visibility whenIsPreferKeepAliveis true, else clear then add; Decorator→Child; other hosts→ObservableRegion.CurrentContent. - Region context —
ObservableRegion.RegionContextattached property for arbitrary data; no change notifications. - Region change notification — Subscribe to
WeakReferenceRegionHub.EventNotifier.ObservableRegionChanged; raised before content changes (before OnNavigatedFrom/OnNavigatedTo). Args: RegionName, FromUri, ToUri, FromTargetName, ToTargetName,NavigationMode(Navigate, Redirect, GoBack, GoForward), andCancelto abort the navigation. - Lifetime — Region host: when a
FrameworkElementwithRegionNameimplements <see cref="IRegionScope"/>, Unloaded unregisters the region and disposes its scope; otherwise the region is not removed on Unloaded (avoids “region not found” when the host is in a tab or lazy-loaded). Named view: when aFrameworkElementwithViewNameimplementsIRegionScope, Unloaded removes that named view; otherwise it is not removed.
Installation
dotnet add package LiteObservableRegions
Targets: .NET Framework 4.6.2, 4.7.2, 4.8, 4.8.1; .NET 5–10 (Windows, WPF). Single package, multi-targeted.
Quick start
1. Register services and set the service provider
In app startup (e.g. App.xaml.cs), build the DI container and set the static service provider so XAML-attached registration can resolve IRegionManager:
using LiteObservableRegions;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddObservableRegions(reg =>
{
reg.AddView<PageA>("ViewA", ServiceLifetime.Scoped);
reg.AddView<PageB>("ViewB", ServiceLifetime.Scoped);
});
// Optional: services.AddSingleton<IRegionHostContentAdapter, MyAdapter>();
var provider = services.BuildServiceProvider();
WeakReferenceRegionHub.ServiceProvider = provider;
2. Define a region in XAML
The host is the element that receives the active view (e.g. a ContentControl or a Grid). Set RegionName on that element. Accepts "region://Name" or "Name" (normalized by the library).
<ContentControl xmlns:r="http://schemas.github.com/liteobservableregions/2026/xaml"
r:ObservableRegion.RegionName="MainRegion" />
Or use a Grid as host — content is set on the Grid via ObservableRegion.CurrentContent; bind a child (e.g. ContentPresenter) to that attached property on the ancestor, or use a single ContentControl as host instead.
Named views (no DI): set ViewName on a child of the host. The first path segment is the target name used for navigation.
<Grid r:ObservableRegion.RegionName="region://TestGridRegion">
<Grid r:ObservableRegion.ViewName="region://TestGridRegion/View1" />
<Grid r:ObservableRegion.ViewName="region://TestGridRegion/View2" />
</Grid>
Here the host is the outer Grid; content is shown via CurrentContent on that Grid. For a single child host like ContentControl, put RegionName on the ContentControl so content goes to Content.
3. Navigate
IRegionManager manager = WeakReferenceRegionHub.RegionManager;
manager.Navigate(new Uri("region://MainRegion/ViewA")); // push onto back stack
manager.Redirect(new Uri("region://MainRegion/ViewB")); // replace, clear back stack
if (manager.CanGoBack("MainRegion"))
manager.GoBack("MainRegion");
if (manager.CanGoForward("MainRegion"))
manager.GoForward("MainRegion");
IRegion region = manager.GetRegion("MainRegion");
Uri current = region?.CurrentUri;
object host = region?.Host; // IRegion: Name, Host, CurrentUri, CanGoBack, CanGoForward
Advanced: manager.Regions is a Dictionary<string, RegionState> (Host, BackStack, ForwardStack, CurrentEntry, NamedViews, Scope).
4. Region change notification and cancellation
WeakReferenceRegionHub.EventNotifier.ObservableRegionChanged is raised before the region content is updated. Set e.Cancel = true to prevent the navigation.
WeakReferenceRegionHub.EventNotifier.ObservableRegionChanged += (sender, e) =>
{
// e.RegionName, e.FromUri, e.ToUri, e.FromTargetName, e.ToTargetName, e.Mode, e.Cancel
if (someCondition)
e.Cancel = true;
};
e.Mode is NavigationMode: Navigate, Redirect, GoBack, GoForward.
Region URIs
- Format:
region://RegionName/TargetName?param1=value1¶m2=value2 - Scheme:
RegionUriParser.Scheme("region"). - Region name — Authority part; must match a registered region. Preserved casing (URI host is not used for casing).
- Target name — First path segment; view identifier (named view or registry key).
- Query — Optional; parsed into
NavigationContext.Parametersand passed toINavigationAware.
Helpers:
RegionUriParser.NormalizeRegionName(value)— stripsregion://prefix if present.RegionUriParser.TryParse(uri, out regionName, out targetName, out parameters)— returns false if scheme or target missing.RegionUriParser.ParseQuery(query)— returns dictionary of query parameters.RegionUriParser.BuildUri(regionName, targetName, parameters)— parameters optional.
For navigation you must include a target: region://MainRegion/View1. Region name only (region://MainRegion) is valid for RegionName in XAML; the library normalizes it.
Attached properties (ObservableRegion)
| Property | Type | Description |
|---|---|---|
| RegionName | string | On the host element. Registers the element as a region. Accepts "region://Name" or "Name". |
| ViewName | string | On a child of the host. Value like region://RegionName/View1; the child is registered as the view for that target (no DI). |
| CurrentContent | object | Set by the library; current view in the region. Can be bound. |
| RegionContext | object | Arbitrary data; no change handling. |
View resolution order
When navigating to a target name in a region:
- Named views — If the region has a view registered for that name (via
ViewName), that instance is used (weak reference; re-resolved from DI if collected). - DI — Otherwise resolved from
IRegionViewRegistryandIServiceProvider: Transient (new each time), Scoped (per-region scope), Singleton (cached per region+target).
Register view types with AddObservableRegions(reg => reg.AddView<T>("TargetName", ServiceLifetime.Scoped)) or, for registry only, AddRegionViews(reg => ...) then register IRegionManager yourself.
Customizing how content is displayed
Implement IRegionHostContentAdapter (single method: SetContent(DependencyObject host, object content)) and register it in DI before AddObservableRegions. The default adapter:
ContentControl→ setContentFrame→Navigate(content)Panel/ItemsControl→ ifIsPreferKeepAliveis true (default): add child if not present, then set visibility (active = Visible, others = Collapsed); if false: clear then addDecorator→ setChild- Any other host →
ObservableRegion.SetCurrentContent(host, content)
Duplicate names and cleanup
- Same RegionName — Registering again replaces the previous region: existing scope is disposed, new host is the only one for that name.
- Same ViewName (same region) — Registering again overwrites the previous named view for that target.
Clear: WeakReferenceRegionHub.Clear() (or IRegionManager.Clear()) clears all named views and the singleton view cache; does not unregister regions or navigation stacks.
API overview
- LiteObservableRegions:
WeakReferenceRegionHub(ServiceProvider, RegionManager, EventNotifier, Clear),ObservableRegion,RegionUriParser,RegionChangedEventArgs,NavigationMode,NavigationContext,DefaultRegionHostContentAdapter,RegionServiceCollectionExtensions(AddRegionViews, AddObservableRegions),RegionManager,RegionState,ViewRegistration,NavigationEntry. - LiteObservableRegions.Abstractions:
IRegionManager,IRegionNavigation,IRegion,IRegionViewRegistry,IRegionHostContentAdapter,INavigationAware,IRegionScope.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0-windows7.0 is compatible. net6.0-windows was computed. net6.0-windows7.0 is compatible. net7.0-windows was computed. net7.0-windows7.0 is compatible. net8.0-windows was computed. 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. |
| .NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 is compatible. net481 is compatible. |
-
.NETFramework 4.6.2
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
.NETFramework 4.7.2
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
.NETFramework 4.8
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
.NETFramework 4.8.1
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net10.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net5.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net6.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net7.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net8.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
-
net9.0-windows7.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.