Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/Menu/HamburgerMenu/ViewModel.md
2026-04-17 14:55:32 -04:00

7.8 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/Menu/HamburgerMenu/ViewModel/HamburgerMenuViewModel.cs
2026-04-16T04:48:30.206063+00:00 Qwen/Qwen3-Coder-Next-FP8 1 462d2b26bf58cd93

ViewModel

Documentation: HamburgerMenuViewModel


1. Purpose

The HamburgerMenuViewModel class serves as the MVVM-compliant view model for the applications hamburger menu UI component. It manages the state and behavior of the menu—including item list, enabled/disabled status, busy state, and context menu construction—while acting as a bridge between the view (IHamburgerMenuView) and the broader system via Prisms event aggregation and Unity dependency injection. It subscribes to system-wide events (e.g., test lifecycle, busy indicators, notifications) to dynamically update its state and exposes interaction requests for modal UI (notifications, confirmations). It is a shared singleton (per container) responsible for rendering a context menu populated from a string array and raising a delegate when menu items are selected.


2. Public Interface

  • IHamburgerMenuView View { get; set; }
    Reference to the associated view; set during construction and used to bind DataContext.

  • InteractionRequest<Notification> NotificationRequest { get; }
    Prism interaction request used to trigger notification popups (e.g., informational messages).

  • InteractionRequest<Confirmation> ConfirmationRequest { get; }
    Prism interaction request used to trigger confirmation dialogs (e.g., yes/no prompts).

  • event PropertyChangedEventHandler PropertyChanged;
    Standard INotifyPropertyChanged implementation for data binding.

  • void OnPropertyChanged(string propertyName);
    Raises the PropertyChanged event for the specified property.

  • ContextMenu GetContextMenu();
    Returns the lazily-built ContextMenu instance. Builds it on first call if not already constructed. Thread-safe via lock(MyLock).

  • void SetMenuItems(string[] items);
    Sets the list of menu item labels and immediately rebuilds the context menu.

  • void ClearMenuItems();
    Clears the internal _menuItems array and triggers a rebuild (resulting in an empty menu).

  • void EnableMenu(bool enable);
    Sets IsEnabled to enable, updating the UI state.

  • void Unset();
    Currently empty; no-op.

  • void OnSetActive();
    Currently empty; no-op.

  • void Cleanup();
    Currently empty; no-op.

  • Task CleanupAsync();
    Returns Task.CompletedTask; no-op.

  • void Initialize();
    Overload variants (Initialize(), Initialize(object), Initialize(object, object)) are present but all currently no-op.

  • Task InitializeAsync();
    Overload variants (InitializeAsync(), InitializeAsync(object)) are present but all return Task.CompletedTask; no-op.

  • void Activated();
    Currently empty; no-op.

  • bool IsEnabled { get; private set; }
    Indicates whether the menu is enabled. Default true. Updated via EnableMenu(), OnTestEvent(), or internal logic.

  • bool IsBusy { get; set; }
    Indicates whether the menu is in a busy state (e.g., during test execution). Bound to BusyIndicatorChangeNotification event.

  • bool IsMenuIncluded { get; set; }
    Indicates whether the hamburger menu is included in the UI. Not used internally—likely for view-level visibility binding.

  • bool IsNavigationIncluded { get; set; }
    Indicates whether navigation controls are included in the UI. Not used internally—likely for view-level visibility binding.

  • MenuItemPressedDelegate MenuItemPressed { get; set; }
    Delegate invoked when a menu item is pressed. Signature: void Delegate(string id). The id passed is the Header of the selected MenuItem.


3. Invariants

  • View.DataContext is always set to this in the constructor.
  • _contextMenu is lazily initialized on first call to GetContextMenu() and rebuilt only when _menuItems changes (via SetMenuItems() or ClearMenuItems()).
  • _menuItems is never null; it is initialized to new string[0] and cleared to new string[0].
  • IsEnabled defaults to true.
  • IsBusy is updated synchronously on the publisher thread (via ThreadOption.PublisherThread) in response to BusyIndicatorChangeNotification.
  • Thread safety for context menu construction is ensured via lock(MyLock) in GetContextMenu() and BuildContextMenu().
  • Automation IDs are set on the ContextMenu ("HamburgerMenu") and each MenuItem ("MenuItem_{ItemName}", with spaces removed).
  • MenuItemPressed is invoked with the Header string of the selected MenuItem.

4. Dependencies

Imports/References (from source):

  • System.ComponentModel, System.ComponentModel.Composition (MEF)
  • Prism.Events, Prism.Regions (Prism framework)
  • Unity (Unity DI container)
  • DTS.Common.Events (custom event types: RaiseNotification, BusyIndicatorChangeNotification, TestEvent)
  • DTS.Common.Interface.Menu.HamburgerMenu (interface IHamburgerMenuViewModel)
  • DTS.Common.Interactivity (interaction request types: Notification, Confirmation)
  • System.Windows.Controls, System.Windows.Automation

Depends on:

  • IHamburgerMenuView (view interface)
  • IRegionManager, IEventAggregator, IUnityContainer (Prism/Unity infrastructure)
  • TestEvent, BusyIndicatorChangeNotification, RaiseNotification (custom events via IEventAggregator)

Used by:

  • Likely consumed by IHamburgerMenuView (WPF view) via data binding.
  • Other modules may publish TestEvent, BusyIndicatorChangeNotification, or RaiseNotification to control its behavior.

5. Gotchas

  • Empty lifecycle methods: Initialize*, Cleanup*, Unset, OnSetActive, and Activated are all no-ops. If lifecycle management is expected, this may be incomplete or deferred to the view.
  • MenuItemPressed is a delegate, not an event: It is declared as public MenuItemPressedDelegate MenuItemPressed { get; set; }, meaning it can be overwritten and is not thread-safe for multicast subscriptions. Callers must ensure safe assignment.
  • IsDirty property exists but is never set: Declared as public bool IsDirty { get; private set; }, but never assigned—likely unused or incomplete.
  • IsMenuIncluded and IsNavigationIncluded are never set internally: Only exposed as properties; their values must be set externally (e.g., by view or another VM), but no logic uses them.
  • AutomationProperties.AutomationIdProperty is hardcoded: Menu item IDs are derived by removing spaces from the header (item.Replace(" ", "")). This may cause collisions if headers differ only by whitespace (e.g., "Run Test" vs "RunTest" both become "MenuItem_RunTest").
  • GetContextMenu() returns the same instance after first build: Repeated calls return the cached _contextMenu. If _menuItems changes but GetContextMenu() is called before SetMenuItems()/ClearMenuItems() triggers BuildContextMenu(), stale items may be returned.
  • OnTestEvent() toggles IsEnabled only on TestStarted/TestEnded: If TestEventArg.Status is anything else (e.g., TestRunning), IsEnabled remains unchanged—assumes only two statuses.
  • Thread safety: Only GetContextMenu() and BuildContextMenu() are thread-safe. Other property setters (e.g., IsBusy) assume caller handles thread affinity (though IsBusy setter uses OnPropertyChanged, which may marshal to UI thread depending on binding context—not guaranteed).
  • No unsubscription from events: The constructor subscribes to events but there is no IDisposable implementation or Unsubscribe() call—potential memory leak if the VM outlives its intended lifetime.

None of the above are necessarily bugs, but they are non-obvious and require awareness during maintenance or extension.