Skip to main content

Navigation Architecture

Overview

The MepApps.Dash.Inv.Batch.MiniMrpOrderCreation dashboard implements a sophisticated navigation architecture built on WPF/MVVM principles, utilizing the MepDash module's navigation services to provide seamless transitions between different functional areas of the MRP order creation workflow.

Key Concepts

  • Service-based Navigation: Leverages dependency injection for navigation services
  • View-First Approach: Views are registered and discovered through service providers
  • Navigation Context: Maintains state and parameters during navigation transitions
  • Event-Driven Updates: Uses notification patterns for navigation state changes

Implementation Details

Core Navigation Infrastructure

The navigation system is centered around the IBasicMepNavigationService interface, which provides the fundamental navigation capabilities:

// From MainViewModel.cs (lines 64-65)
var navigationService = MainView.MepPluginServiceProvider.GetService<IBasicMepNavigationService>();
navigationService.NavigateToNewUserControl<WarehouseOrderingView>();

This service-based approach ensures loose coupling between views and maintains testability of navigation logic.

BaseRouteableViewModel Pattern

All navigable view models inherit from BaseRouteableViewModel, which provides:

// MepApps.Dash.Inv.Batch.MiniMrpOrderCreation/Models/BindingModels/BaseRouteableViewModel.cs
public abstract class BaseRouteableViewModel : BaseViewModel, INavigationTarget
{
// Provides navigation lifecycle hooks
// Manages navigation state
// Handles parameter passing between views
}

This base class ensures consistent navigation behavior across all view models and provides:

  • Navigation lifecycle management (OnNavigatedTo, OnNavigatingFrom)
  • Parameter handling for data passing between views
  • State preservation during navigation
  • Memory cleanup on navigation away

The dashboard implements a linear workflow navigation pattern:

  1. Entry Point (MainView)

    • Initializes core services
    • Performs database validation
    • Navigates to WarehouseOrderingView
  2. Primary Workflow (WarehouseOrderingView)

    • Main operational view for MRP calculations
    • Handles inventory analysis and order creation
    • Routes to completion or dialog views
  3. Completion Flow (InvOrderingCompletionView)

    • Displays results of order creation
    • Provides navigation back to primary workflow

Navigation services are registered through the RegisterServiceProvider:

// Services/RegisterServiceProvider.cs
public class RegisterServiceProvider : ARegisterService
{
public override void RegisterServices(IServiceCollection services)
{
// Navigation service registrations
services.AddTransient<NavToOrderCompletion>();
services.AddTransient<IBasicMepNavigationService, BasicMepNavigationService>();
}
}

The navigation system maintains state through several mechanisms:

1. Navigation Context Preservation

// From WarehouseOrderingViewModel.cs (lines 382-383)
var navBackRelayCommand = new RelayCommandAsync(ResetSearch);
_navToOrderCompletion.NavToOrderCompletionView(results, navBackRelayCommand);

2. Host Notificator Pattern

// From MainViewModel.cs (lines 11, 24)
private readonly BasicMepNavigationUiHostNotificator _navigationUiHostNotificator;
_navigationUiHostNotificator.MainContentChanged += (sender, e) => SetMainContent(sender);

This pattern ensures the main container is notified of content changes and can update the UI accordingly.

The system implements navigation guards to ensure data integrity:

// From WarehouseOrderingViewModel.cs (lines 84-86)
case "OrderingEnabled":
if (_orderingEnabled)
await SearchCmd.ExecuteAsync().ConfigureAwait(false);

Navigation is conditionally enabled based on:

  • User permissions
  • Data validation state
  • Business rule compliance
  • Required field completion

Back Navigation Handling

Back navigation is handled through command patterns:

// From InvOrderingCompletionViewModel.cs (lines 62-73)
private RelayCommandAsync _navigateBackCmd;
public RelayCommandAsync NavigateBackCmd
{
get => _navigateBackCmd;
set
{
if (_navigateBackCmd != value)
{
_navigateBackCmd = value;
OnPropertyChanged("NavigateBackCmd");
}
}
}

This approach ensures:

  • Clean state reset on back navigation
  • Proper disposal of resources
  • Maintenance of navigation history

Examples

Example 1: Initial Navigation Setup

// MainViewModel.cs - Initial navigation on startup
public async Task InitializeAsync()
{
// Initialize services
await _mepSettingsService.InitializeDefaultAsync().ConfigureAwait(true);
await _databaseValidationService.InitializeAsync().ConfigureAwait(true);

// Navigate to main workflow
var navigationService = MainView.MepPluginServiceProvider.GetService<IBasicMepNavigationService>();
navigationService.NavigateToNewUserControl<WarehouseOrderingView>();
}

Example 2: Workflow Navigation with Parameters

// NavToOrderCompletion.cs - Navigate with result data
public void NavToOrderCompletionView(CreateOrdersResult results, RelayCommandAsync navBackCommand)
{
var completionView = _serviceProvider.GetService<InvOrderingCompletionView>();
var completionViewModel = completionView.DataContext as InvOrderingCompletionViewModel;

completionViewModel.SetOrderResult(results);
completionViewModel.NavigateBackCmd = navBackCommand;

_navigationService.NavigateToExistingUserControl(completionView);
}

Example 3: Content Container Update

// MainViewModel.cs - Dynamic content update
public void SetMainContent(object content)
{
Dispatcher.CurrentDispatcher.Invoke(() =>
{
if (_logger.IsEnabled(LogLevel.Trace))
_logger.LogTrace("CHANGING MAIN CONTENT to {ContentIsNull}, {NameOfContent} {SizeOfContent}",
content == null, content?.GetType().Name, content?.ToString().Length);

MainContent = content;
});
}

Best Practices

  • Always preserve necessary state before navigation
  • Use parameter objects for complex data passing
  • Implement proper disposal in OnNavigatingFrom

Memory Management

  • Dispose of event subscriptions on navigation away
  • Clear large data collections when leaving views
  • Use weak references for cross-view model communication

Error Handling

  • Implement try-catch blocks in navigation methods
  • Provide user feedback for navigation failures
  • Log navigation events for debugging

Performance Optimization

  • Load data asynchronously during navigation
  • Use lazy loading for heavy views
  • Implement view caching for frequently accessed screens

Common Pitfalls

Circular Navigation References

Avoid creating circular dependencies between navigation services and view models. Use dependency injection to break circular references.

Memory Leaks from Event Handlers

Always unsubscribe from events when navigating away:

public void Dispose()
{
_navigationUiHostNotificator.MainContentChanged -= SetMainContent;
}

Synchronous Navigation in Async Context

Ensure navigation calls are properly awaited when in async methods to prevent race conditions.

Summary

The navigation architecture in MiniMrpOrderCreation provides a robust, scalable foundation for complex workflow navigation. By leveraging service-based navigation, event-driven updates, and proper state management, the system ensures smooth user experiences while maintaining code maintainability and testability. The architecture supports both linear workflows and dynamic navigation patterns, making it suitable for complex business processes.