Skip to main content

Navigation Architecture

Overview

The MepApps EFT Remittance Dashboard implements a simplified navigation architecture designed for focused workflow execution. Unlike multi-page applications, this dashboard uses a single-view pattern with embedded functionality, leveraging the MepDash module's navigation infrastructure for seamless integration within the SYSPRO environment.

Key Concepts

  • Single-View Architecture: The entire application operates within a single main view
  • BaseRouteableViewModel Pattern: Provides navigation capability even in single-view scenarios
  • Container-Based Navigation: Leverages SYSPRO's container navigation system
  • View Injection: Dynamic content loading through dependency injection

Implementation Details

The navigation architecture is built on the BaseRouteableViewModel class, which serves as the foundation for view models that participate in navigation:

// MepApps.Dash.Ap.Rpt.EftRemittance/ViewModels/BaseRouteableViewModel.cs
public abstract class BaseRouteableViewModel : BaseViewModel, INavigationTarget
{
protected BaseRouteableViewModel()
{
}

public virtual Task NavigatedFromAsync(INavigationRequest request)
{
return Task.CompletedTask;
}

public virtual Task NavigatedToAsync(INavigationRequest request)
{
return Task.CompletedTask;
}
}

This base class implements the INavigationTarget interface from the MepDash module, enabling navigation lifecycle events even though the dashboard maintains a single-view approach.

Main View Navigation Structure

The MainViewModel serves as the navigation host, managing the primary content area:

// MepApps.Dash.Ap.Rpt.EftRemittance/ViewModels/MainViewModel.cs
public class MainViewModel : BaseRouteableViewModel
{
private object _mainContent;
public object MainContent
{
get => _mainContent;
set
{
if (_mainContent != value)
{
_mainContent = value;
OnPropertyChanged();
}
}
}
}

The MainContent property acts as a content presenter, allowing for potential future expansion while currently hosting the EftRemit_RunReportsView.

Container Integration

The navigation system integrates with SYSPRO's container infrastructure through the MainView:

// MepApps.Dash.Ap.Rpt.EftRemittance/Views/MainView.xaml.cs
public partial class MainView : UserControl
{
private readonly IContainerEvents? _events;
private readonly IContainerNavigation? _navigation;

public MainView(ISharedShellInterface sharedShellInterface,
IContainerEvents? events,
IContainerNavigation? navigation,
IMepPluginServiceHandler mepPluginServiceHandler)
{
_events = events;
_navigation = navigation;
// Container navigation is available but not actively used
// in the single-view pattern
}
}

View Initialization Flow

The navigation initialization follows this sequence:

  1. Service Registration: Views and ViewModels are registered as singletons
  2. Dependency Resolution: The DI container resolves all dependencies
  3. View Construction: MainView is instantiated with all required services
  4. ViewModel Binding: The EftRemit_RunReportsViewModel is bound to its view
  5. Content Assignment: The view is set as MainContent
// MepApps.Dash.Ap.Rpt.EftRemittance/ViewModels/MainViewModel.cs
public MainViewModel(Dispatcher dispatcher,
PluginSysproDataContext pluginSysproDataContext,
EftRemit_RunReportsView eftRemit_RunReportsView,
IEftRemit_RunReportsViewModel eftRemit_RunReportsViewModel)
{
_eftRemit_RunReportsView.DataContext = _eftRemit_RunReportsViewModel;
MainContent = _eftRemit_RunReportsView;
}

Examples

Example 1: Navigation State Management

While the dashboard doesn't navigate between pages, it manages navigation state for potential expansions:

public class MainViewModel : BaseRouteableViewModel
{
public override async Task NavigatedToAsync(INavigationRequest request)
{
// Handle navigation to this dashboard
// Could receive parameters from SYSPRO menu
if (request?.Parameters?.ContainsKey("PaymentNumber") == true)
{
// Pre-select a specific payment if launched with context
var paymentNumber = request.Parameters["PaymentNumber"];
// Initialize view with specific payment
}
await base.NavigatedToAsync(request);
}
}

Example 2: Future Navigation Expansion

The architecture supports adding multiple views without restructuring:

// Potential future implementation
public void NavigateToDetailView(PaymentDetail payment)
{
var detailView = _serviceProvider.GetService<PaymentDetailView>();
var detailViewModel = _serviceProvider.GetService<IPaymentDetailViewModel>();

detailViewModel.Initialize(payment);
detailView.DataContext = detailViewModel;
MainContent = detailView; // Switches the view
}

State Preservation

The single-view pattern naturally preserves state since views are registered as singletons:

// Services/RegisterServiceProvider.cs
serviceCollection.AddSingleton<MainViewModel>();
serviceCollection.AddSingleton<IEftRemit_RunReportsViewModel, EftRemit_RunReportsViewModel>();
serviceCollection.AddSingleton<EftRemit_RunReportsView>();

This ensures that:

  • User selections persist during the session
  • Filter states are maintained
  • Processing status is retained

Memory Management

The singleton pattern requires careful memory management:

public override Task NavigatedFromAsync(INavigationRequest request)
{
// Clean up any subscriptions or resources
// This is called when navigating away from the dashboard
return base.NavigatedFromAsync(request);
}

While not explicitly implemented, the architecture supports navigation guards:

public override async Task<bool> CanNavigateFromAsync()
{
if (HasUnsavedChanges())
{
var result = await ShowConfirmationDialog("Unsaved changes will be lost. Continue?");
return result;
}
return true;
}

Integration with SYSPRO Navigation

The dashboard integrates with SYSPRO's navigation through:

  1. Menu Integration: Launched from SYSPRO menu system
  2. Container Events: Responds to SYSPRO container events
  3. Navigation Context: Can receive parameters from SYSPRO context
  4. Back Navigation: Handled by SYSPRO container

Best Practices

  1. Singleton Services: Use singleton registration for views and view models
  2. State Management: Implement proper cleanup in NavigatedFromAsync
  3. Parameter Handling: Always validate navigation parameters
  4. Error Boundaries: Implement error handling in navigation methods
  5. Memory Leaks: Dispose of event subscriptions when navigating away

Common Pitfalls

  • Not handling null navigation parameters
  • Forgetting to call base navigation methods
  • Memory leaks from event subscriptions
  • Not preserving state when required

Summary

The EFT Remittance Dashboard implements a streamlined navigation architecture optimized for single-purpose workflow execution. While maintaining compatibility with the full MepDash navigation infrastructure, it focuses on providing a stable, state-preserving environment for remittance processing operations. The architecture is extensible, allowing for future multi-view scenarios while maintaining the current simplicity and efficiency.