11 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | |
|---|---|---|---|---|---|
|
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 Prism’s 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 setsView.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
StandardINotifyPropertyChangedimplementation;OnPropertyChangedraises 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 ofAllISOChannelCodes, bound to the UI. -
ObservableCollection<IChannelCode> UserChannelCodes { get; set; }
Filtered/sorted view ofAllUserChannelCodes, bound to the UI. -
ViewModes ViewMode { get; set; }
Current view mode (ISOorUser). Changing it updatesISOVisibility/UserVisibility. -
Visibility ISOVisibility { get; }
VisibleifViewMode == ViewModes.ISO, elseCollapsed. -
Visibility UserVisibility { get; }
VisibleifViewMode == ViewModes.User, elseCollapsed. -
bool IsBusy { get; set; }
Bound to busy indicator; updated viaOnBusyIndicatorNotification. -
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; }
ReturnsGetAllChannels()→ChannelCode.ChannelCodes. -
bool ShowISOStringBuilder { get; set; },bool ShowChannelCodeLookupHelper { get; set; },bool UniqueISOCodesRequired { get; set; }
UI configuration flags.
Methods
-
void SetPage(object page)
Sets thePageidentifier used in events. -
void OnSetActive()
Loads existing channel codes from DB (ChannelCode.GetExistingChannelCodes), populatesAllISOChannelCodes/AllUserChannelCodes, adds blank trailing rows, sorts, filters, and updatesISOChannelCodes/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:- Deletes removed codes (those with valid IDs not in
All*ChannelCodes). - Updates existing codes (those with valid IDs).
- Inserts new codes (those without valid IDs and not blank).
Returnstrueon success; publishesPageModifiedEvent(Status.Saved)orPageErrorEventon failure.
- Deletes removed codes (those with valid IDs not in
-
void Remove(IChannelCode channel)
Removes a channel from bothAll*and*ChannelCodeslists, adds a blank row if the last row was removed, and publishesPageModifiedEvent(Status.Modified). -
void MarkModified(IChannelCode channel)
Ensures a blank row is added after the modified channel (if it’s the last visible row), and publishesPageModifiedEvent(Status.Modified). -
void Validate(bool bDisplayWindow)
Validates all ISO/User codes: checks for missing code/name, duplicate code+name pairs. Populateserrors/warningslists. IfbDisplayWindow, publishesPageErrorEvent. Returnstrueif no errors. -
void ValidateISO(ref List<string> errors, ref List<string> warnings)
Validates ISO codes only (callsCheckChannelCode). -
void ValidateUser(ref List<string> errors, ref List<string> warnings)
Validates User codes only (callsCheckChannelCode). -
void CopySelected()
Copies selected items (from currentViewMode) intoAll*ChannelCodes(before the trailing blank row), then sorts/filters. -
void DeleteSelected()
Deletes selected items (from currentViewMode), adds blank row if last item deleted, clears selection, and publishesPageModifiedEvent(Status.Modified). -
void SetISOSelection(IChannelCode[] channelCodes),void SetUserSelection(IChannelCode[] channelCodes)
Stores selected items; triggersPageSelectionChangedevent ifViewModematches. -
IChannelCode[] SelectedCodes { get; }
Returns selected items for currentViewMode. -
void Filter(object columnTag, string searchTerm)
Updates_searchTermForFieldand 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)
HandlesRaiseNotificationevents by raisingNotificationRequest. -
void OnBusyIndicatorNotification(bool)
UpdatesIsBusyproperty. -
void ReportErrors(string[] errors)
PublishesPageErrorEvent.
3. Invariants
-
Trailing Blank Row:
AllISOChannelCodesandAllUserChannelCodesalways contain a trailing blankChannelCode(added inOnSetActive,Remove,MarkModified,Paste*,CopySelected,DeleteSelected). This enables adding new entries. -
Filtering Logic:
ISOChannelCodes/UserChannelCodesonly include rows where:- Both
CodeandNameare blank, or Code/Namematches current search term (case-insensitive substring match).
- Both
-
Sorting Logic:
Sorting usesChannelComparer, which:- Treats blank rows (empty
CodeandName) as lowest priority (sorted to bottom). - Uses
NaturalStringComparerfor case-insensitive, culture-aware comparison. - Sorts
Code/Namefields separately for ISO/User modes.
- Treats blank rows (empty
-
Validation Rules:
A channel code is invalid if:Codeis missing (for non-blank rows) → error.Nameis missing (for non-blank rows) → error.- Duplicate
Code+Namepair exists → error.
-
Save Order:
Save()processes deletions → updates → inserts to avoid ID/name conflicts. -
Event Subscription Guard:
_bAddListenersensures only the second instantiation ofChannelCodesListViewModelsubscribes toTextPastedEvent/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.ChannelEnumsAndConstantsEvents.*(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)
ChannelCodesListViewModelis instantiated via Unity (constructor injection).IChannelCodesListViewbinds to its properties/methods.- Other modules subscribe to its events (
PageModifiedEvent,PageErrorEvent,PageSelectionChanged). ChannelCodeCommittedEventpublisher (e.g., a dialog) callsOnChannelCodesCommitted.
5. Gotchas
-
_bAddListenersHack:
A static boolean_bAddListenersprevents first instantiation from subscribing to events (due to app startup ordering). Only the second instance subscribes. This is fragile and non-obvious. -
IsDirtyNever Set:
TheIsDirtyproperty is declared but never updated (no assignment in source). Likely dead code or incomplete implementation. -
SelectedCodesNull Safety:
GetSelectedISOCodes/GetSelectedUserCodesreturnnullif_selectedISOItems/_selectedUserItemsarenull. Consumers must handlenull. -
Paste Behavior Depends on
tag:
PasteIso/PasteUserusetagto determine if pasted data isCodeorName-only (viabCode = tag.Equals("ISOCode")). Iftagis 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. -
OnChannelCodesCommittedLogic Complexity:
The method builds multiple dictionaries (lookup2,isoLookup,userLookup) to avoid duplicates during batch commits. This is error-prone and duplicates logic inSave(). -
ParseTextDelimiter 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. -
ValidateIgnores Blank Rows:
Blank rows (emptyCode/Name) are skipped during validation. This is correct, but the logic is nested insideCheckChannelCode. -
No Undo/Revert:
Changes are published asPageModifiedEvent(Status.Modified)immediately on edit, but no mechanism to revert is visible. -
ChannelCodesFuncUsage Unclear:
ChannelCodesFuncis exposed but its usage (e.g., byGetAllChannels) is not shown in this file. Likely consumed externally. -
UniqueISOCodesRequiredFlag:
The property exists but is never used in validation logic (despite its name). May be a future feature flag. -
NotifySelectionChangedOnly Notifies WhenViewModeMatches:
Selection change events are only published if the currentViewModematches the selection type (ISO/User). This may cause inconsistent selection state ifViewModechanges after selection. -
No Null Checks on
View:
View.DataContext = thisassumesViewis non-null, but no validation exists.