A robust .NET library for implementing navigation stacks with undo/redo support and persistence capabilities.
ktsu.Navigation provides a complete navigation stack implementation that supports:
- Forward/Backward Navigation: Navigate through items with full browser-like back/forward functionality
- Undo/Redo Operations: Complete undo/redo support for all navigation actions
- Persistence: Save and restore navigation state to various storage backends
- Event-Driven Architecture: React to navigation changes with comprehensive event notifications
- Generic Design: Works with any navigation item type implementing
INavigationItem - Factory Pattern: Easy creation of navigation stacks with different configurations
Perfect for applications that need robust navigation management, such as:
- Code editors with file navigation
- Image viewers with browsing history
- Document management systems
- Any application requiring navigation state management
- ✅ NavigateTo, GoBack, GoForward operations
- ✅ Current item tracking with CanGoBack/CanGoForward status
- ✅ Complete navigation history management
- ✅ Forward history clearing when navigating to new items
- ✅ Thread-safe operations
- ✅ Full undo/redo support for navigation operations
- ✅ Configurable history size limits
- ✅ State change notifications
- ✅ Error handling during undo/redo operations
- ✅ JSON file persistence provider
- ✅ In-memory persistence for testing
- ✅ Async operations with cancellation token support
- ✅ Custom persistence provider support
- ✅ Navigation change events (NavigateTo, GoBack, GoForward, Clear)
- ✅ Metadata support for navigation items
- ✅ Generic design for custom navigation item types
- ✅ Factory pattern for easy configuration
Add the NuGet package:
dotnet add package ktsu.Navigationusingktsu.Navigation.Models;usingktsu.Navigation.Services;// Create navigation itemsvarpage1=newNavigationItem("page1","Home Page");varpage2=newNavigationItem("page2","About Page");varpage3=newNavigationItem("page3","Contact Page");// Create a navigation stackvarnavigation=newNavigation<NavigationItem>();// Navigate through itemsnavigation.NavigateTo(page1);// Current: Home Pagenavigation.NavigateTo(page2);// Current: About Pagenavigation.NavigateTo(page3);// Current: Contact Page// Go back and forwardvarprevious=navigation.GoBack();// Current: About Pagevarnext=navigation.GoForward();// Current: Contact Page// Check navigation stateConsole.WriteLine($"Current: {navigation.Current?.DisplayName}");Console.WriteLine($"Can go back: {navigation.CanGoBack}");Console.WriteLine($"Can go forward: {navigation.CanGoForward}");usingktsu.Navigation.Services;// Create navigation with undo/redo supportvarundoRedoProvider=newSimpleUndoRedoProvider(maxHistorySize:50);varnavigation=newNavigation<NavigationItem>(undoRedoProvider);navigation.NavigateTo(page1);navigation.NavigateTo(page2);// Undo the last navigationundoRedoProvider.Undo();// Back to page1// Redo the navigationundoRedoProvider.Redo();// Forward to page2 againusingktsu.Navigation.Services;// Create navigation with JSON file persistencevarpersistenceProvider=newJsonFilePersistenceProvider<NavigationItem>("navigation-state.json");varnavigation=newNavigation<NavigationItem>(undoRedoProvider:null,persistenceProvider:persistenceProvider);navigation.NavigateTo(page1);navigation.NavigateTo(page2);// Save navigation stateawaitnavigation.SaveStateAsync();// Later... restore navigation stateawaitnavigation.LoadStateAsync();Console.WriteLine($"Restored to: {navigation.Current?.DisplayName}");usingktsu.Navigation.Services;// Create providersvarundoRedoProvider=newSimpleUndoRedoProvider();varpersistenceProvider=newJsonFilePersistenceProvider<NavigationItem>("app-navigation.json");// Create navigation with all featuresvarnavigation=newNavigation<NavigationItem>(undoRedoProvider,persistenceProvider);// Subscribe to navigation eventsnavigation.NavigationChanged+=(sender,e)=>{Console.WriteLine($"Navigation: {e.NavigationType}");Console.WriteLine($"From: {e.PreviousItem?.DisplayName??"None"}");Console.WriteLine($"To: {e.CurrentItem?.DisplayName??"None"}");};// Use factory for easier creationvarfactory=newNavigationStackFactory(undoRedoProvider);varanotherNavigation=factory.CreateNavigationStack<NavigationItem>(undoRedoProvider,persistenceProvider);publicclassDocumentNavigationItem:INavigationItem{publicstringId{get;}publicstringDisplayName{get;set;}publicDateTimeCreatedAt{get;}publicIReadOnlyDictionary<string,object>Metadata=>_metadata.AsReadOnly();privatereadonlyDictionary<string,object>_metadata=new();publicDocumentNavigationItem(stringfilePath,stringdisplayName){Id=filePath;DisplayName=displayName;CreatedAt=DateTime.UtcNow;SetMetadata("FilePath",filePath);SetMetadata("FileSize",newFileInfo(filePath).Length);}publicvoidSetMetadata(stringkey,objectvalue)=>_metadata[key]=value;publicboolRemoveMetadata(stringkey)=>_metadata.Remove(key);}// Use with navigationvarnavigation=newNavigation<DocumentNavigationItem>();vardocument=newDocumentNavigationItem("/path/to/file.txt","My Document");navigation.NavigateTo(document);The library follows clean architecture principles with well-separated concerns:
- Models:
NavigationItem,NavigationState- Core data structures - Contracts: Interfaces defining the contracts for all components
- Services: Implementation classes for navigation, persistence, and undo/redo
INavigation<T>: Main navigation operations interfaceINavigationItem: Contract for items that can be navigated toIPersistenceProvider<T>: Contract for persistence implementationsIUndoRedoProvider: Contract for undo/redo implementations
Create custom persistence providers by implementing the IPersistenceProvider<T> interface:
publicclassDatabasePersistenceProvider<T>:IPersistenceProvider<T>whereT:INavigationItem{publicasyncTaskSaveStateAsync(INavigationState<T>state,CancellationTokencancellationToken=default){// Save to databaseawaitTask.CompletedTask;}publicasyncTask<INavigationState<T>?>LoadStateAsync(CancellationTokencancellationToken=default){// Load from databasereturnawaitTask.FromResult<INavigationState<T>?>(null);}// Implement HasSavedState, ClearState, etc.}Contributions are welcome! Please feel free to submit a Pull Request.
MIT License. Copyright (c) ktsu.dev