A Reactive Navigation Framework for ReactiveUI
$ dotnet add package CrissCross.XamFormsA navigation framework and set of UI components for ReactiveUI-based applications across WPF, Avalonia, MAUI, and WinForms.
![]()
CrissCross provides ViewModel-first navigation, hostable navigation surfaces, and a comprehensive WPF UI control set with a strong ReactiveUI focus. It promotes:
Supported platforms and packages:
NuGet packages:
Note: Xamarin.Forms support exists in separate projects but for new apps prefer .NET MAUI.
CrissCross builds on ReactiveUI to provide ViewModel-first navigation:
Register your ViewModels and Views with Splat�s Locator or Microsoft.Extensions.DependencyInjection. CrissCross uses the locator to resolve Views for navigation targets.
public class AppBootstrapper : RxObject
{
public AppBootstrapper()
{
this.BuildComplete(() =>
{
// Example VM/View registrations using Splat
AppLocator.CurrentMutable.RegisterConstant(new MainViewModel());
AppLocator.CurrentMutable.Register<IViewFor<MainViewModel>>(() => new MainView());
AppLocator.CurrentMutable.RegisterConstant(new FirstViewModel());
AppLocator.CurrentMutable.Register<IViewFor<FirstViewModel>>(() => new FirstView());
AppLocator.CurrentMutable.SetupComplete();
});
}
}public partial class MainWindow : NavigationWindow<MainWindowViewModel>
{
public MainWindow()
{
InitializeComponent(); // Ensure x:Name is set on the Window (e.g., "mainWindow")
this.WhenActivated(d =>
{
// Bind back command, etc
NavBack.Command = ReactiveCommand.Create(() => this.NavigateBack(), CanNavigateBack).DisposeWith(d);
// Navigate to a start VM
this.NavigateToView<MainViewModel>();
});
}
}public class MainViewModel : RxObject
{
public MainViewModel()
{
this.BuildComplete(() =>
{
// Target a specific host by name (Window x:Name)
this.NavigateToView<FirstViewModel>("mainWindow");
});
}
}public partial class MainView : ReactiveUserControl<MainViewModel>
{
public MainView()
{
InitializeComponent();
this.WhenActivated(_ => { /* bindings, commands */ });
}
}NavigationWindow (WPF): A Window that exposes a ViewModelRoutedViewHost and transition support
FluentNavigationWindow (WPF UI): A fluent-styled NavigationWindow with additional title content areas and Transition
NavigationUserControl (WPF UI, Avalonia): A hostable control version of the navigation container (for regions/panels)
ViewModelRoutedViewHost (WPF): Core host implementation
HostName: Set on NavigationWindow/NavigationUserControl (typically from x:Name) to route cross-host navigation
A comprehensive set of fluent controls and services designed for ReactiveUI apps. Highlights include:
Include the control resources by merging the ControlsDictionary:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ControlsDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>For page-based apps using WPF UI, use the host builder extensions:
private static readonly IHost _host = Host.CreateDefaultBuilder()
.ConfigureCrissCrossForPageNavigation<MainWindow, DashboardPage>()
.ConfigureServices((context, services) =>
{
services.AddSingleton<MainWindowViewModel>();
services.AddSingleton<DashboardPage>().AddSingleton<DashboardViewModel>();
services.AddSingleton<DataPage>().AddSingleton<DataViewModel>();
services.AddSingleton<SettingsPage>().AddSingleton<SettingsViewModel>();
services.AddSingleton<LoginPage>().AddSingleton<LoginViewModel>();
})
.Build();Wire up and start in App.xaml.cs, then navigate using IPageService or NavigationView.
A powerful navigation control that manages a journal and hierarchical navigation stack:
The control maintains a NavigationStack and history so you can build rich shell navigation experiences.
public partial class MainUserControl : NavigationUserControl<MainWindowViewModel>
{
public MainUserControl()
{
InitializeComponent();
this.WhenActivated(d =>
{
this.NavigateToView<MainViewModel>();
_NavBack!.Command = ReactiveCommand.Create(() => this.NavigateBack(), this.CanNavigateBack()).DisposeWith(d);
});
}
}MAUI helpers integrate with ReactiveUI.Maui. Register your VMs/Views with DI and navigate using the same NavigateToView/Back helpers where applicable. Prefer this approach over Xamarin.Forms for new apps.
Packages:
CrissCross.WPF.WebView2 provides a NavigationWebView that hosts WebView2 while allowing WPF content overlays:
xmlns:webv="https://github.com/reactivemarbles/CrissCross"
<webv:WebView2Wpf x:Name="WebView2Wpf" AutoDispose="True">
<!-- overlay WPF content here -->
</webv:WebView2Wpf>WebView2Wpf.Source = new Uri("https://www.reactiveui.net/");CrissCross.WPF.Plot adds Reactive plotting components:
Install: Install-Package CrissCross.WPF.Plot
Persist and track control/window state:
_tracker?.Configure<MainWindow>()
.Id(w => w.Name, $"[Width={SystemParameters.VirtualScreenWidth},Height{SystemParameters.VirtualScreenHeight}]")
.Properties(w => new { w.Height, w.Width, w.Left, w.Top, w.WindowState })
.PersistOn(w => nameof(w.Closing))
.StopTrackingOn(w => nameof(w.Closing));Browse these projects to see real-world usage patterns, navigation setup, and control bindings.
Prevent multiple instances using Make.SingleInstance in App:
protected override void OnStartup(StartupEventArgs e)
{
Make.SingleInstance("MyUniqueAppName ddd81fc8-9107-4e33-b848-cac4c3ec3d2a");
base.OnStartup(e);
}Issues and PRs are welcome. Please include platform, .NET version, and a minimal repro where applicable.
MIT � ReactiveUI Association Incorporated