This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Model/ChannelCodeType.cs
- DataPRO/Modules/Channels/ChannelCodes/Model/ChannelCode.cs
generated_at: "2026-04-16T04:56:25.345352+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "8041292bb801532f"
---
# Model
## Documentation: ChannelCode Module
---
### 1. Purpose
This module provides data access and modeling for *channel codes*—lookup values used to categorize or classify channels in the system (e.g., ISO-standardized codes vs. user-defined codes). It defines a base abstract class `ChannelCodeType` for retrieving static type metadata and a concrete class `ChannelCode` that represents individual channel code entries, including persistence operations (insert/update/delete) and caching of ISO codes from a static text file. The module serves as the data layer for channel code management, bridging the database (`sp_ChannelCodeTypeGet`, `sp_ChannelCodesGet`) and file-based ISO code definitions.
---
### 2. Public Interface
#### `ChannelCodeType.GetChannelCodeTypeLookup()`
```csharp
public static IDictionary<short, string> GetChannelCodeTypeLookup()
```
Retrieves all channel code types from the database via stored procedure `sp_ChannelCodeTypeGet`. Returns a dictionary mapping `Id` (short) to `CodeType` (string), representing the type categories (e.g., ISO, User). Parameters passed to the stored procedure (`@Id`, `@CodeType`) are null, indicating no filtering.
#### `ChannelCode` class
*Inherits from `DTS.Common.Classes.ChannelCodes.ChannelCode` and implements `IChannelCode`.*
- **Constructors**
- `ChannelCode()`
Initializes a new `ChannelCode` with `CodeType = ISO` and registers the `PasteCommand`.
- `ChannelCode(IChannelCode channelCode)`
Copies properties from an existing `IChannelCode` instance and registers `PasteCommand`.
- `ChannelCode(IDataRecord sqlReader, IDictionary<short, string> channelCodeLookup)`
Populates the instance from a database row (`sqlReader`) using the provided `channelCodeLookup`. Maps `CodeTypeInt` (short) to a `ChannelCodeType` enum value (`ISO` or `User`) via string comparison against `ChannelEnumsAndConstants.IsoCodeTypeString` and `ChannelEnumsAndConstants.UserCodeTypeString`.
- **Properties**
- `bool HasValidId()`
Returns `true` if `Id >= 0`.
- `bool IsBlank()`
Returns `true` if both `Name` and `Code` are `null` or empty.
- `int SelectedChannelType`
Gets/sets a legacy dropdown index (0 = ISO, 1 = User) based on `CodeType`. *Deprecated per inline comment.*
- `Dictionary<string, string> PossibleChannels { get; private set; }`
Publicly readable dictionary (currently unused in source; likely intended for channel mappings).
- `static IList<IChannelCode> ChannelCodes { get; }`
Returns a combined list of *all* channel codes: user-defined codes (from DB via `GetExistingChannelCodes`) + ISO codes (from `ISOChannelCodes`). Uses a shared lookup from `GetChannelCodeTypeLookup()`.
- `static IList<IChannelCode> ISOChannelCodes { get; }`
Lazily loads ISO codes from `ISOPossibleChannels.txt` (comma-separated: `Code,Name`). Caches in `_isoChannelCodes` after first access. Thread-safe via `lock(RefreshLock)`.
- **Methods**
- `static ChannelCode[] GetExistingChannelCodes(IDictionary<short, string> lookup)`
Fetches all user-defined channel codes from DB via `sp_ChannelCodesGet`, returning an array of `ChannelCode` instances. Parameters passed to the stored procedure (`@Id`, `@Code`, `@Name`, `@CodeType`) are null (no filtering).
- `void Delete()`
Calls `DbOperations.ChannelCodesDelete(Id, null, null, null)` to remove the channel code *from the lookup table only* (does not affect existing channel instances referencing it).
- `void Save(IDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup)`
Calls `DbOperations.ChannelCodesUpdate(restrictedLookup, this)` to persist changes to the channel code *lookup table*.
- `void Insert(IDictionary<ChannelEnumsAndConstants.ChannelCodeType, short> lookup)`
Calls `DbOperations.ChannelCodesInsert(restrictedLookup, this, out id)` to insert a new channel code. On success (`hr == 0`), sets `Id` to the returned value.
- `protected static long GetLong(OleDbDataReader reader, string field)`
Helper for legacy OleDb access; returns `long.MinValue` on `DBNull`. *Not used in current code.*
- `protected static DateTime GetDate(OleDbDataReader reader, string field)`
Helper for legacy OleDb access; returns `DateTime.MinValue` on `DBNull`. *Not used in current code.*
#### Command
- `PasteCommand` (public property, type `ICommand`)
Initialized as `PasteCommandClass(PASTE_ID)` in `RegisterCommands()`. A no-op `Paste` handler is defined but empty. Registered via `CommandManager.RegisterClassCommandBinding`.
---
### 3. Invariants
- **`Id` validity**: `HasValidId()` requires `Id >= 0`. Negative IDs are considered invalid.
- **Code type mapping**: `CodeType` must be either `ChannelEnumsAndConstants.ChannelCodeType.ISO` or `ChannelEnumsAndConstants.ChannelCodeType.User`. Mapping from DB `CodeTypeInt` relies on exact string matches against `IsoCodeTypeString` and `UserCodeTypeString`.
- **ISO codes are static**: `ISOChannelCodes` are loaded once and cached in `_isoChannelCodes`. They are *not* persisted to the database.
- **Persistence scope**: `Insert`, `Save`, and `Delete` operations affect *only the channel code lookup table*, not any channels that may reference the code.
- **Thread safety**: ISO code loading uses `lock(RefreshLock)` to ensure single initialization.
- **Null handling**: `IsBlank()` treats `null` and empty strings identically.
---
### 4. Dependencies
#### **Dependencies *of* this module**
- **Database**:
- Stored procedures: `sp_ChannelCodeTypeGet`, `sp_ChannelCodesGet`
- Table columns: `Id`, `Code`, `Name`, `CodeTypeInt`
- **File system**:
- `ISOPossibleChannels.txt` (comma-separated: `Code,Name`) in app base directory.
- **External types**:
- `DTS.Common.Storage.DbOperations` (provides `GetSQLCommand`, `ChannelCodesDelete`, `ChannelCodesUpdate`, `ChannelCodesInsert`)
- `DTS.Common.Classes.ChannelCodes.ChannelCode` (base class)
- `DTS.Common.Interface.Channels.ChannelCodes.IChannelCode` (interface)
- `DTS.Common.Enums.Channels.ChannelEnumsAndConstants` (defines `ChannelCodeType`, `IsoCodeTypeString`, `UserCodeTypeString`)
- `System.Data.SqlClient`, `System.Data`, `System.IO`, `System.Windows.Input`
#### **Dependencies *on* this module**
- Any module needing channel code metadata or management (e.g., UI dropdowns, channel assignment logic).
- `ISOChannelCodes` implies a hard dependency on the presence and format of `ISOPossibleChannels.txt`.
---
### 5. Gotchas
- **`SelectedChannelType` is legacy/deprecated**: The property is tied to a dropdown that may no longer exist. Its use is discouraged.
- **`PasteCommand` is non-functional**: The `Paste` handler is empty; the command is registered but does nothing.
- **`PossibleChannels` is unused**: The property is declared but never populated in the source.
- **ISO codes are *not* persisted**: Changes to `ISOChannelCodes` (e.g., via `Insert`/`Save`) will not affect `ISOPossibleChannels.txt`. This file is read-only at runtime.
- **`Delete`/`Save`/`Insert` do not cascade**: Operations affect only the channel code *definition* (lookup), not any existing channels that reference the code.
- **Thread-safety limitation**: ISO code loading is thread-safe for initialization, but no caching invalidation mechanism exists (codes are assumed immutable).
- **`GetLong`/`GetDate` are dead code**: OleDb-specific helpers with no callers in this module. Likely remnants of legacy migration code.
- **`ChannelCodes` property is expensive**: Each access calls `GetChannelCodeTypeLookup()` and `GetExistingChannelCodes()`, which hit the database. Caching externally is recommended if used repeatedly.
- **No validation on `Code`/`Name`**: The module does not enforce uniqueness or non-empty values beyond `IsBlank()`. Business rules may be enforced elsewhere.
- **`Id` assignment is conditional**: `Insert` only sets `Id` if `hr == 0`; callers must check the return value or handle failure.
*None identified from source alone.* (Note: The above are inferred from explicit comments and code structure—not hallucinated.)

View File

@@ -0,0 +1,47 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Properties/Settings.Designer.cs
- DataPRO/Modules/Channels/ChannelCodes/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T04:56:06.604797+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "4a79c622a52c39c9"
---
# Properties
## Documentation: ChannelCodes.Properties.Settings
### 1. Purpose
This module defines a strongly-typed settings class (`Settings`) for the `ChannelCodes` assembly, enabling centralized access to application-level configuration values via the .NET `ApplicationSettingsBase` infrastructure. It serves as the runtime interface for reading (and potentially writing) user- or application-scoped settings, generated automatically by Visual Studios settings designer. The class is internal and sealed, intended solely for use within the `ChannelCodes` module to manage persistent configuration state.
### 2. Public Interface
The module exposes **one public static property**:
- **`Settings.Default`**
- **Signature**: `public static Settings Default { get; }`
- **Behavior**: Returns the singleton instance of the `Settings` class, synchronized for thread safety via `ApplicationSettingsBase.Synchronized`. This instance provides access to all application settings defined in the projects `.settings` file (e.g., `Properties/Settings.settings`). Note: The actual settings properties (e.g., `string SomeSetting { get; set; }`) are *not present in the provided source* and must be defined in the corresponding auto-generated `Settings.cs` (not included here). This file only declares the class skeleton and the `Default` accessor.
### 3. Invariants
- The `Settings` class inherits from `ApplicationSettingsBase`, which enforces standard .NET settings semantics:
- Settings values are persisted per-user (user-scoped) or per-application (application-scoped), depending on their `UserScopedSetting`/`ApplicationScopedSetting` attributes (not visible here).
- Thread-safety is guaranteed for the `Default` instance via synchronization.
- The class is `internal sealed`, meaning it cannot be inherited or accessed outside the `ChannelCodes.Properties` namespace.
- The `defaultInstance` field is initialized once during static construction and never reassigned.
### 4. Dependencies
- **Dependencies *of* this module**:
- `System.Configuration` (for `ApplicationSettingsBase` and related types).
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`).
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`).
- **Dependencies *on* this module**:
- Other parts of the `ChannelCodes` module (or dependent modules) likely consume `Settings.Default` to read configuration values. However, no explicit usages are visible in the provided files.
### 5. Gotchas
- **Auto-generated code**: This file is auto-generated by Visual Studios settings designer. Manual edits will be overwritten on regeneration.
- **Missing settings definitions**: The provided snippet only shows the class declaration and `Default` property. Actual settings (e.g., `public string ChannelMapPath { get; set; }`) are defined in the corresponding `Settings.Designer.cs` *before* regeneration or in the `.settings` designer file (not included). Without those, `Settings.Default` has no accessible properties beyond inherited `ApplicationSettingsBase` members.
- **No write support implied**: While `ApplicationSettingsBase` supports setting values, this file does not indicate whether settings are read-only (application-scoped) or read/write (user-scoped). Behavior depends on attributes in the full `Settings.cs` (not provided).
- **Thread-safety scope**: Synchronization applies only to the `Default` instance retrieval—not to individual property access or modification. Concurrent writes to settings properties may still require external locking.
- **No versioning or migration logic**: The assembly version (`1.0.0.0`) suggests no settings schema evolution handling is visible here. Migration of settings across versions would require explicit `SettingsUpgrade` logic (absent in this snippet).
> **Note**: Full behavior (e.g., available settings, their types, scopes, and defaults) cannot be determined from the provided files alone. Consult the `ChannelCodes.Properties.Settings.settings` designer file or the full `Settings.Designer.cs` (which typically contains the property definitions).

View File

@@ -0,0 +1,104 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/Resources/TranslateExtension.cs
- DataPRO/Modules/Channels/ChannelCodes/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T04:55:56.339798+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "3fc30f8d93dc5d3b"
---
# Resources
## Documentation: `TranslateExtension` Markup Extension
---
### **Purpose**
The `TranslateExtension` class provides a XAML markup extension for localized string lookup within the `ChannelCodes` module. It enables declarative binding of UI text to resource keys defined in `StringResources.resx`, supporting internationalization by resolving keys at runtime using the .NET `ResourceManager`. This allows UI elements (e.g., `TextBlock.Text`, `Button.Content`) to display culture-specific strings without hardcoding values or writing code-behind.
---
### **Public Interface**
#### `TranslateExtension(string key)`
**Constructor**
- **Parameter**: `key` (`string`) The resource key to look up (e.g., `"ChannelCode"`, `"DuplicateISOChannelCode"`).
- **Behavior**: Stores the key for later resolution. No validation is performed at construction time.
#### `public override object ProvideValue(IServiceProvider serviceProvider)`
**Markup Extension Entry Point**
- **Parameter**: `serviceProvider` (`IServiceProvider`) Provides services to the markup extension (unused in current implementation).
- **Returns**:
- `string`: The localized string corresponding to `_key`, or
- `NotFound` (`"#stringnotfound#"`): If `_key` is `null` or empty,
- `NotFound + " " + _key`: If `_key` is non-empty but no matching resource string is found.
- **Behavior**:
1. Checks if `_key` is `null` or empty → returns `"#stringnotfound#"`.
2. Calls `StringResources.ResourceManager.GetString(_key)` to retrieve the localized string.
3. If `GetString` returns `null`, appends the key to the `NotFound` prefix (e.g., `"#stringnotfound# MissingISOCode"`).
> **Note**: The `MarkupExtensionReturnType` attribute indicates this extension always returns a `string`.
---
### **Invariants**
1. **Key Handling**:
- Empty or `null` keys are treated as invalid and always resolve to `"#stringnotfound#"`.
- Non-empty keys that lack a corresponding resource entry resolve to `"#stringnotfound# <key>"`.
2. **Resource Lookup**:
- Uses `StringResources.ResourceManager.GetString(key)` with the current UI culture (via `CultureInfo`).
- No fallback logic beyond the `null` check in `ProvideValue`.
3. **Thread Safety**:
- `StringResources.ResourceManager` is lazily initialized and cached (per `StringResources` class), but `TranslateExtension` itself is stateful per instance (stores `_key`). Reuse across threads is safe *only if* the same instance is not shared concurrently (standard for markup extensions).
---
### **Dependencies**
#### **Depends On**
- `System.Windows.Markup.MarkupExtension` (WPF framework)
- `ChannelCodes.Resources.StringResources` (strongly-typed resource class)
- Specifically relies on `StringResources.ResourceManager` and its `GetString(string)` method.
- `System` (for `string.IsNullOrEmpty`, `ResourceManager`, `CultureInfo`)
#### **Used By**
- XAML files in the `ChannelCodes` module (e.g., `*.xaml` pages) where localized text is declared via `{local:Translate KeyName}`.
- Example usage:
```xaml
<TextBlock Text="{local:Translate ChannelCode}" />
```
---
### **Gotchas**
1. **No Resource Key Validation at Compile Time**:
- Typos in resource keys (e.g., `"ChannelCodee"` instead of `"ChannelCode"`) will silently resolve to `"#stringnotfound# ChannelCodee"` at runtime.
- No build-time or design-time warning is generated for missing keys.
2. **Hardcoded `NotFound` Prefix**:
- The `"#stringnotfound#"` prefix is hardcoded and may be visible in the UI if a key is missing. This is likely intentional for debugging but could confuse end users.
3. **No Caching of Resolved Strings**:
- `ProvideValue` calls `ResourceManager.GetString(_key)` on every invocation. While `ResourceManager` caches resources internally, repeated use of the same key in a UI (e.g., in a `DataTemplate`) may incur unnecessary lookups. Consider caching if performance is critical.
4. **Culture Handling**:
- Respects `StringResources.Culture` (settable via `StringResources.Culture = ...`). If `Culture` is `null`, the UI threads `CurrentUICulture` is used.
- No explicit handling for fallback cultures (e.g., `en-US` → `en`).
5. **Auto-Generated Resource Class**:
- `StringResources.Designer.cs` is auto-generated. Manual edits will be overwritten. New strings must be added via `.resx` files and regenerated.
6. **No Support for Format Strings**:
- `TranslateExtension` does not support parameterized resources (e.g., `"Error: {0} is missing"`). While `StringResources` has entries like `DuplicateISOChannelCode` (which uses `{0}`), the extension itself does not accept or apply formatting arguments.
- To use formatted strings, the caller must manually construct the key (e.g., `"DuplicateISOChannelCode"`), but the resolved string will remain unformatted unless the *caller* applies `string.Format` (not done here).
7. **WPF-Specific**:
- Depends on `System.Windows.Markup`, making it unusable outside WPF (e.g., in MAUI, WinUI, or console apps).
---
*Documentation generated from source files dated to .NET Framework 4.0 and WPF. No external dependencies beyond standard .NET libraries.*

View File

@@ -0,0 +1,70 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/View/ChannelCodesListView.xaml.cs
generated_at: "2026-04-16T04:56:21.286180+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0dcb0611d2fa879c"
---
# View
## **1. Purpose**
This module implements the WPF view layer (`ChannelCodesListView`) for a channel codes management UI, adhering to the `IChannelCodesListView` interface. It provides interactive controls for viewing, editing, sorting, filtering, and selecting channel codes in two distinct modes: ISO and User. The view binds to an `IChannelCodesListViewModel` and handles user interactions such as text edits, checkbox toggles, column header clicks, and selection changes, delegating state management and validation logic to the view model.
---
## **2. Public Interface**
The class `ChannelCodesListView` implements `IChannelCodesListView` (via `partial class` + `: IChannelCodesListView`) and exposes only its constructor publicly. All other members are private event handlers wired via XAML. No public methods or properties are defined in this file.
### **Constructor**
- **`ChannelCodesListView()`**
Initializes the WPF component by calling `InitializeComponent()`. Sets up the visual tree defined in `ChannelCodesListView.xaml`.
All other functionality is exposed indirectly via event handlers attached to XAML elements (e.g., `KeyDown`, `TextChanged`, `SelectionChanged`, `Click`), which internally interact with the `DataContext` (expected to be an `IChannelCodesListViewModel`).
---
## **3. Invariants**
- The `DataContext` **must** be an instance implementing `IChannelCodesListViewModel`; otherwise, most event handlers silently return.
- Column sorting and filtering rely on the `Tag` property of `GridViewColumnHeaderSearchable` elements (e.g., `ISOCodeColumnHeader`, `UserCodeColumnHeader`). These tags must be non-null and correspond to valid filter/sort keys expected by the view model.
- Selection changes in either `ISOChannelCodesListView` or `UserChannelCodesListView` must result in exactly one `IChannelCode` item being selected per list (based on handler logic in `ISO_Checked`/`User_Checked` and selection handlers), though the code does not enforce uniqueness beyond what the view model allows.
- The `ChannelCodeBuilder_OnChannelCodeSelected` handler assumes that if `channelCode.Name` is null/whitespace, it should be overwritten with the selected `name` parameter.
- Text/keydown handlers for `ChannelCodeTextBoxUser`, `DisplayNameTextBoxUser`, `ChannelCodeTextBoxIso`, and `DisplayNameTextBoxIso` always call `MarkModified(channelCode)` and then invoke `ValidateUser(...)` or `ValidateISO(...)` with unused `List<string>` parameters—indicating validation results are likely ignored or handled internally by the view model.
---
## **4. Dependencies**
### **Imports / External Types Used**
- `System.Collections.Generic`, `System.Windows`, `System.Windows.Controls`, `System.Windows.Media` — standard WPF and .NET types.
- `DTS.Common.Controls` — likely contains custom controls (e.g., `GridViewColumnHeaderSearchable`).
- `DTS.Common.Enums.Channels` — contains `ChannelEnumsAndConstants.ChannelCodeType`.
- `DTS.Common.Interface.Channels.ChannelCodes` — defines `IChannelCodesListView`, `IChannelCodesListViewModel`, `IChannelCode`.
- `DTS.Common.Utils` — contains `Utils.FindChild<T>` helper.
- `ChannelCodes.Resources.StringResources` — static resource class for localized strings (e.g., `"ISOCode"`, `"UserChannelName"`).
### **Inferred Dependencies**
- **Depends on**:
- `IChannelCodesListViewModel` (via `DataContext`) for filtering, sorting, validation, and selection state.
- `IChannelCode` interface for individual code objects.
- Custom control `GridViewColumnHeaderSearchable` for searchable column headers.
- `ChannelCodesListView.xaml` (implicit dependency via `InitializeComponent()`).
- **Depended on by**:
- Likely consumed by a parent view or shell that binds an `IChannelCodesListViewModel` instance to its `DataContext`.
---
## **5. Gotchas**
- **Silent failures**: Most handlers return early if `DataContext` is not `ChannelCodesListViewModel` (or `IChannelCodesListViewModel`), leading to no-op behavior without logging or exceptions.
- **Unused validation outputs**: All `ValidateUser`/`ValidateISO` calls instantiate and pass `new List<string>()` for `out`/`ref` parameters, but the lists are never used—suggesting validation errors are either ignored or handled via side effects (e.g., raising `INotifyDataErrorInfo` or UI bindings).
- **Redundant selection handling**: Multiple event handlers (`ISO_Checked`, `User_Checked`, `*SelectionChanged`, `*TextBox*SelectionChanged`) all call `vm.SetISOSelection(...)` or `vm.SetUserSelection(...)`, potentially causing duplicate or conflicting selection updates. This may indicate legacy or overlapping event wiring.
- **Hit-test complexity**: `ISOChannelCodesListView_PreviewMouseLeftButtonUp` and `UserChannelCodesListView_PreviewMouseLeftButtonUp` use multiple hit tests (`VisualTreeHelper.HitTest`, `InputHitTest`) and descendant checks to determine sort triggers—fragile and hard to maintain. Sorting is triggered on clicks anywhere in a column header, including `TextBlock`s with specific localized text.
- **Commented-out code**: A `ChannelType_SelectionChanged` handler is commented out, suggesting incomplete or deprecated logic.
- **Assumed control types**: Handlers assume specific control types (`TextBox`, `ListView`, `TextBlock`, `Control`) and cast them directly—could throw if XAML changes unexpectedly.
None identified beyond the above.

View File

@@ -0,0 +1,233 @@
---
source_files:
- DataPRO/Modules/Channels/ChannelCodes/ViewModel/ChannelCodesListViewModel.cs
generated_at: "2026-04-16T04:56:00.828392+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "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.