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

11 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/Modules/Channels/ChannelCodes/ViewModel/ChannelCodesListViewModel.cs
2026-04-16T04:56:00.828392+00:00 Qwen/Qwen3-Coder-Next-FP8 1 a1a75e2ca7b7b574

ViewModel

1. Purpose

The ChannelCodesListViewModel class serves as the view model for managing and displaying channel codes (both ISO and User-defined) in a data entry UI. It orchestrates data loading, filtering, sorting, editing (including paste, copy, delete, and validation), and persistence operations for channel codes. It acts as the intermediary between the UI (IChannelCodesListView) and the underlying data layer (ChannelCode, ChannelCodeType), leveraging Prisms event aggregation for decoupled communication and Unity for dependency injection. Its primary role is to expose collections of channel codes (ISOChannelCodes, UserChannelCodes) and provide methods to manipulate and validate them before saving to the database.


2. Public Interface

Properties

  • IChannelCodesListView View { get; set; }
    Reference to the associated view; view model sets View.DataContext = this.

  • InteractionRequest<Notification> NotificationRequest { get; }
    Prism interaction request used to show notification popups (e.g., errors, info).

  • InteractionRequest<Confirmation> ConfirmationRequest { get; }
    Prism interaction request used to prompt for user confirmation (e.g., delete).

  • event PropertyChangedEventHandler PropertyChanged
    Standard INotifyPropertyChanged implementation; OnPropertyChanged raises it.

  • List<IChannelCode> AllISOChannelCodes { get; set; }
    Full list of ISO channel codes (including blank trailing row), used for sorting/filtering.

  • List<IChannelCode> AllUserChannelCodes { get; set; }
    Full list of User channel codes (including blank trailing row), used for sorting/filtering.

  • ObservableCollection<IChannelCode> ISOChannelCodes { get; set; }
    Filtered/sorted view of AllISOChannelCodes, bound to the UI.

  • ObservableCollection<IChannelCode> UserChannelCodes { get; set; }
    Filtered/sorted view of AllUserChannelCodes, bound to the UI.

  • ViewModes ViewMode { get; set; }
    Current view mode (ISO or User). Changing it updates ISOVisibility/UserVisibility.

  • Visibility ISOVisibility { get; }
    Visible if ViewMode == ViewModes.ISO, else Collapsed.

  • Visibility UserVisibility { get; }
    Visible if ViewMode == ViewModes.User, else Collapsed.

  • bool IsBusy { get; set; }
    Bound to busy indicator; updated via OnBusyIndicatorNotification.

  • bool IsDirty { get; private set; } (Note: never set in source — likely unused or bug)

  • bool IsReadOnly { get; set; }
    Controls editability of the view (e.g., based on permissions).

  • bool IsMenuIncluded { get; set; }, bool IsNavigationIncluded { get; set; }
    UI layout toggles.

  • object Page { get; private set; }
    Identifier for the page this VM serves (used in events to route to correct consumer).

  • Func<IList<IChannelCode>> ChannelCodesFunc { get; }
    Returns GetAllChannels()ChannelCode.ChannelCodes.

  • bool ShowISOStringBuilder { get; set; }, bool ShowChannelCodeLookupHelper { get; set; }, bool UniqueISOCodesRequired { get; set; }
    UI configuration flags.

Methods

  • void SetPage(object page)
    Sets the Page identifier used in events.

  • void OnSetActive()
    Loads existing channel codes from DB (ChannelCode.GetExistingChannelCodes), populates AllISOChannelCodes/AllUserChannelCodes, adds blank trailing rows, sorts, filters, and updates ISOChannelCodes/UserChannelCodes. Logs exceptions.

  • void Unset()
    Clears all channel code collections and raises property change notifications.

  • void Initialize(), void Initialize(object), Task InitializeAsync(), void Activated(), void Cleanup(), Task CleanupAsync()
    No-op stubs (likely required by Prism interface contracts).

  • bool Save()
    Persists changes in three steps:

    1. Deletes removed codes (those with valid IDs not in All*ChannelCodes).
    2. Updates existing codes (those with valid IDs).
    3. Inserts new codes (those without valid IDs and not blank).
      Returns true on success; publishes PageModifiedEvent(Status.Saved) or PageErrorEvent on failure.
  • void Remove(IChannelCode channel)
    Removes a channel from both All* and *ChannelCodes lists, adds a blank row if the last row was removed, and publishes PageModifiedEvent(Status.Modified).

  • void MarkModified(IChannelCode channel)
    Ensures a blank row is added after the modified channel (if its the last visible row), and publishes PageModifiedEvent(Status.Modified).

  • void Validate(bool bDisplayWindow)
    Validates all ISO/User codes: checks for missing code/name, duplicate code+name pairs. Populates errors/warnings lists. If bDisplayWindow, publishes PageErrorEvent. Returns true if no errors.

  • void ValidateISO(ref List<string> errors, ref List<string> warnings)
    Validates ISO codes only (calls CheckChannelCode).

  • void ValidateUser(ref List<string> errors, ref List<string> warnings)
    Validates User codes only (calls CheckChannelCode).

  • void CopySelected()
    Copies selected items (from current ViewMode) into All*ChannelCodes (before the trailing blank row), then sorts/filters.

  • void DeleteSelected()
    Deletes selected items (from current ViewMode), adds blank row if last item deleted, clears selection, and publishes PageModifiedEvent(Status.Modified).

  • void SetISOSelection(IChannelCode[] channelCodes), void SetUserSelection(IChannelCode[] channelCodes)
    Stores selected items; triggers PageSelectionChanged event if ViewMode matches.

  • IChannelCode[] SelectedCodes { get; }
    Returns selected items for current ViewMode.

  • void Filter(object columnTag, string searchTerm)
    Updates _searchTermForField and re-applies filter (FilterIso/FilterUser).

  • void Sort(object columnTag, bool bColumnClick)
    Updates sort field/direction and re-applies sort (SortIso/SortUser) + filter.

  • void OnRaiseNotification(NotificationContentEventArgs)
    Handles RaiseNotification events by raising NotificationRequest.

  • void OnBusyIndicatorNotification(bool)
    Updates IsBusy property.

  • void ReportErrors(string[] errors)
    Publishes PageErrorEvent.


3. Invariants

  • Trailing Blank Row:
    AllISOChannelCodes and AllUserChannelCodes always contain a trailing blank ChannelCode (added in OnSetActive, Remove, MarkModified, Paste*, CopySelected, DeleteSelected). This enables adding new entries.

  • Filtering Logic:
    ISOChannelCodes/UserChannelCodes only include rows where:

    • Both Code and Name are blank, or
    • Code/Name matches current search term (case-insensitive substring match).
  • Sorting Logic:
    Sorting uses ChannelComparer, which:

    • Treats blank rows (empty Code and Name) as lowest priority (sorted to bottom).
    • Uses NaturalStringComparer for case-insensitive, culture-aware comparison.
    • Sorts Code/Name fields separately for ISO/User modes.
  • Validation Rules:
    A channel code is invalid if:

    • Code is missing (for non-blank rows) → error.
    • Name is missing (for non-blank rows) → error.
    • Duplicate Code + Name pair exists → error.
  • Save Order:
    Save() processes deletions → updates → inserts to avoid ID/name conflicts.

  • Event Subscription Guard:
    _bAddListeners ensures only the second instantiation of ChannelCodesListViewModel subscribes to TextPastedEvent/ChannelCodeCommittedEvent (a workaround for app startup ordering).


4. Dependencies

Imports/Usings (External Dependencies)

  • Prism.Events (IEventAggregator, EventBase)
  • Prism.Regions (IRegionManager)
  • Unity (IUnityContainer)
  • DTS.Common.*:
    • Enums.Channels.ChannelEnumsAndConstants
    • Events.* (TextPastedEvent, ChannelCodeCommittedEvent, PageModifiedEvent, PageErrorEvent, PageSelectionChanged)
    • Interface.Channels.ChannelCodes.* (IChannelCodesListView, IChannelCodesListViewModel, IChannelCode)
    • Utilities.* (NaturalStringComparer, Logging.APILogger)
    • Interactivity (InteractionRequest<Notification/Confirmation>)

Internal Dependencies

  • ChannelCodes.Model (ChannelCode, ChannelCodeType)
  • DTS.Common.Enums (UIItemStatus, PageModifiedArg.Status)
  • Resources.StringResources (for localized error messages)

Consumers (Inferred)

  • ChannelCodesListViewModel is instantiated via Unity (constructor injection).
  • IChannelCodesListView binds to its properties/methods.
  • Other modules subscribe to its events (PageModifiedEvent, PageErrorEvent, PageSelectionChanged).
  • ChannelCodeCommittedEvent publisher (e.g., a dialog) calls OnChannelCodesCommitted.

5. Gotchas

  • _bAddListeners Hack:
    A static boolean _bAddListeners prevents first instantiation from subscribing to events (due to app startup ordering). Only the second instance subscribes. This is fragile and non-obvious.

  • IsDirty Never Set:
    The IsDirty property is declared but never updated (no assignment in source). Likely dead code or incomplete implementation.

  • SelectedCodes Null Safety:
    GetSelectedISOCodes/GetSelectedUserCodes return null if _selectedISOItems/_selectedUserItems are null. Consumers must handle null.

  • Paste Behavior Depends on tag:
    PasteIso/PasteUser use tag to determine if pasted data is Code or Name-only (via bCode = tag.Equals("ISOCode")). If tag is incorrect, data may be misassigned.

  • Duplicate Code Handling:
    Validation flags duplicate code+name pairs as errors, but allows duplicate codes with different names. This may be intentional (e.g., ISO codes can map to multiple names), but could be confusing.

  • OnChannelCodesCommitted Logic Complexity:
    The method builds multiple dictionaries (lookup2, isoLookup, userLookup) to avoid duplicates during batch commits. This is error-prone and duplicates logic in Save().

  • ParseText Delimiter Fallback:
    Tries to split by ,, then \t, then ;. If none yield 2 tokens, the line is skipped. This may silently fail if data uses unexpected delimiters.

  • Validate Ignores Blank Rows:
    Blank rows (empty Code/Name) are skipped during validation. This is correct, but the logic is nested inside CheckChannelCode.

  • No Undo/Revert:
    Changes are published as PageModifiedEvent(Status.Modified) immediately on edit, but no mechanism to revert is visible.

  • ChannelCodesFunc Usage Unclear:
    ChannelCodesFunc is exposed but its usage (e.g., by GetAllChannels) is not shown in this file. Likely consumed externally.

  • UniqueISOCodesRequired Flag:
    The property exists but is never used in validation logic (despite its name). May be a future feature flag.

  • NotifySelectionChanged Only Notifies When ViewMode Matches:
    Selection change events are only published if the current ViewMode matches the selection type (ISO/User). This may cause inconsistent selection state if ViewMode changes after selection.

  • No Null Checks on View:
    View.DataContext = this assumes View is non-null, but no validation exists.