Files

232 lines
16 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- DataPRO/Modules/TestSetups/Imports/TTS/ViewModel/DigitalOutputChannelsViewModel.cs
- DataPRO/Modules/TestSetups/Imports/TTS/ViewModel/LevelTriggerViewModel.cs
- DataPRO/Modules/TestSetups/Imports/TTS/ViewModel/DigitalInputChannelsViewModel.cs
- DataPRO/Modules/TestSetups/Imports/TTS/ViewModel/TOMChannelsViewModel.cs
generated_at: "2026-04-16T04:50:15.817999+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "a0d4b98d2d85c9f6"
---
# Documentation: TTS Import Channel ViewModels
## 1. Purpose
This module provides view models for managing hardware channel assignments in TTS (Test Technology Suite) import workflows, specifically for digital output (DO), digital input (DI), TOM (Twin Oscillator Module, i.e., squib channels), and level trigger configurations. Each view model acts as a bridge between the UI and the underlying test setup data (`ITTSSetup`), hardware scan results (`IDASHardware`), and sensor-to-channel mapping (`EIDMappingEvent`). They handle real-time updates via Prism events, support interactive channel assignment/removal/enable/disable operations, and maintain UI state such as busy indicators and selection states. The module exists to decouple UI logic from core test setup management and to provide a consistent, event-driven pattern for channel configuration across different channel types.
## 2. Public Interface
### `DigitalOutputChannelsViewModel`
- **`DigitalOutputChannelsViewModel(IDigitalOutputChannelsView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Constructor. Initializes event subscriptions, UI interaction requests, and view binding.
- **`IDigitalOutputChannelsView View { get; set; }`**
Reference to the associated view.
- **`InteractionRequest<Notification> NotificationRequest { get; }`**
Prism interaction request for displaying notifications.
- **`InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
Prism interaction request for confirmation dialogs.
- **`ObservableCollection<DASChannel> DASChannels { get; set; }`**
Collection of digital output channels discovered during hardware scan, with optional sensor assignments.
- **`DASChannel SelectedDASChannel { get; set; }`**
Currently selected channel in the UI.
- **`string EnableOrDisableText { get; }`**
UI text for the enable/disable button (e.g., “Enable” or “Disable”) based on channel state.
- **`bool IsBusy { get; set; }`**
Indicates whether a background operation is in progress.
- **`bool IsMenuIncluded`, `IsNavigationIncluded { get; set; }`**
UI layout flags (not used in logic).
- **`void Cleanup()`, `Task CleanupAsync()`**
No-op stubs; no cleanup logic implemented.
- **`void Initialize(...)`, `Task InitializeAsync(...)`**
No-op stubs; initialization is handled via constructor event subscriptions.
- **`void Activated()`**
No-op stub.
- **`event PropertyChangedEventHandler PropertyChanged`**
Standard `INotifyPropertyChanged` implementation.
- **`void OnPropertyChanged(string propertyName)`**
Raises `PropertyChanged` event.
### `LevelTriggerViewModel`
- **`LevelTriggerViewModel(ILevelTriggerView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Constructor. Initializes event subscriptions and UI interaction requests.
- **`ILevelTriggerView View { get; set; }`**
Reference to the associated view.
- **`InteractionRequest<Notification> NotificationRequest { get; }`**
Prism interaction request for notifications.
- **`InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
Prism interaction request for confirmations.
- **`ILevelTrigger[] LevelTriggers { get; }`**
Exposes `_setup.LevelTriggers` (read-only).
- **`bool IsBusy { get; set; }`**
Busy state indicator.
- **`bool IsMenuIncluded`, `IsNavigationIncluded { get; set; }`**
UI layout flags.
- **`void Cleanup()`, `Task CleanupAsync()`**
No-op stubs.
- **`void Initialize(...)`, `Task InitializeAsync(...)`**
No-op stubs.
- **`void Activated()`**
No-op stub.
- **`event PropertyChangedEventHandler PropertyChanged`**
Standard `INotifyPropertyChanged` implementation.
- **`void OnPropertyChanged(string propertyName)`**
Raises `PropertyChanged` event.
### `DigitalInputChannelsViewModel`
- **`DigitalInputChannelsViewModel(IDigitalInputChannelsView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Constructor. Initializes event subscriptions and UI interaction requests.
- **`IDigitalInputChannelsView View { get; set; }`**
Reference to the associated view.
- **`InteractionRequest<Notification> NotificationRequest { get; }`**
Prism interaction request for notifications.
- **`InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
Prism interaction request for confirmations.
- **`ObservableCollection<DASChannel> DASChannels { get; set; }`**
Collection of digital input channels discovered during hardware scan.
- **`ObservableCollection<ITTSChannelRecord> RemainingChannels { get; set; }`**
Channels from the test setup that are not yet assigned to hardware.
- **`ITTSChannelRecord SelectedRemainingChannel { get; set; }`**
Currently selected unassigned channel.
- **`DASChannel SelectedDASChannel { get; set; }`**
Currently selected hardware channel.
- **`bool AssignEnabled`, `RemoveEnabled`, `EnableOrDisableEnabled { get; set; }`**
UI state flags for command buttons (set via `DetermineRemoveEnableStatus()`).
- **`string EnableOrDisableText { get; }`**
Button text for enable/disable operation.
- **`DelegateCommand AssignCommand { get; }`**
Command to assign a `RemainingChannels` item to a `DASChannel`.
- **`DelegateCommand RemoveCommand { get; }`**
Command to remove a hardware assignment from a `DASChannel`.
- **`DelegateCommand EnableOrDisableCommand { get; }`**
Command to toggle channel disabled state.
- **`bool IsBusy { get; set; }`**
Busy state indicator.
- **`bool IsMenuIncluded`, `IsNavigationIncluded { get; set; }`**
UI layout flags.
- **`void Cleanup()`, `Task CleanupAsync()`**
No-op stubs.
- **`void Initialize(...)`, `Task InitializeAsync(...)`**
No-op stubs.
- **`void Activated()`**
No-op stub.
- **`event PropertyChangedEventHandler PropertyChanged`**
Standard `INotifyPropertyChanged` implementation.
- **`void OnPropertyChanged(string propertyName)`**
Raises `PropertyChanged` event.
### `TOMChannelsViewModel`
- **`TOMChannelsViewModel(ITOMChannelsView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
Constructor. Initializes event subscriptions and UI interaction requests.
- **`ITOMChannelsView View { get; set; }`**
Reference to the associated view.
- **`InteractionRequest<Notification> NotificationRequest { get; }`**
Prism interaction request for notifications.
- **`InteractionRequest<Confirmation> ConfirmationRequest { get; }`**
Prism interaction request for confirmations.
- **`ObservableCollection<Model.DASChannel> DASChannels { get; set; }`**
Collection of TOM (squib) channels discovered during hardware scan (every 2nd channel in hardware list).
- **`ObservableCollection<ITTSChannelRecord> RemainingChannels { get; set; }`**
Unassigned TOM channels from the test setup.
- **`ITTSChannelRecord SelectedRemainingChannel { get; set; }`**
Currently selected unassigned channel.
- **`Model.DASChannel SelectedDASChannel { get; set; }`**
Currently selected hardware channel.
- **`bool AssignEnabled`, `RemoveEnabled`, `EnableOrDisableEnabled { get; set; }`**
UI state flags for command buttons.
- **`string EnableOrDisableText { get; }`**
Button text for enable/disable operation.
- **`DelegateCommand AssignCommand { get; }`**
Command to assign a `RemainingChannels` item to a `DASChannel`.
- **`DelegateCommand RemoveCommand { get; }`**
Command to remove a hardware assignment.
- **`DelegateCommand EnableOrDisableCommand { get; }`**
Command to toggle channel disabled state.
- **`bool IsBusy { get; set; }`**
Busy state indicator.
- **`bool IsMenuIncluded`, `IsNavigationIncluded { get; set; }`**
UI layout flags.
- **`void Cleanup()`, `Task CleanupAsync()`**
No-op stubs.
- **`void Initialize(...)`, `Task InitializeAsync(...)`**
No-op stubs.
- **`void Activated()`**
No-op stub.
- **`event PropertyChangedEventHandler PropertyChanged`**
Standard `INotifyPropertyChanged` implementation.
- **`void OnPropertyChanged(string propertyName)`**
Raises `PropertyChanged` event.
## 3. Invariants
- **`_setup` and `_hardware` must be non-null** before `OnAssignedChannelsChangedEvent` (or equivalent) logic executes; otherwise, the method returns early.
- **`DASChannel` instances are constructed with an `IHardwareChannel` and optionally an `ITTSSetup`** (e.g., `new DASChannel(ch, _setup)` in `DigitalOutputChannelsViewModel`).
- **`DASChannel.SetITTSChannelRecord(ITTSChannelRecord)`** is used to associate a hardware channel with a logical channel record; passing `null` removes the association.
- **`DASChannel.EID` is populated from `_hardwareChannelIdToSensorId` (or `_sensorIdToChannelId` in `LevelTriggerViewModel`) only if the hardware channel ID exists as a key.**
- **`IsBusy` is updated only via `OnBusyIndicatorNotification(bool)`**, triggered by `BusyIndicatorChangeNotification` event.
- **`IsMenuIncluded` and `IsNavigationIncluded` are UI flags only; they do not affect business logic.**
- **`IsDirty` is declared but never set; it remains `false` throughout the lifetime of the view model.**
- **`EnableOrDisableText` is computed from `SelectedDASChannel?.Channel?.Disabled` and `StringResources` constants.**
- **`LevelTriggers` is read-only and derived from `_setup.LevelTriggers`; no direct modification is performed in `LevelTriggerViewModel`.**
- **`TOMChannelsViewModel` only processes hardware channels where `ch.IsSquib` is true, and iterates hardware channels in pairs (`i += 2`) to select squib channels.**
- **`DigitalInputChannelsViewModel` and `TOMChannelsViewModel` share identical command logic (`Assign`, `Remove`, `EnableOrDisable`) and state management (`DetermineRemoveEnableStatus`).**
## 4. Dependencies
### Internal Dependencies (from source)
- **`DTS.Common.Events.TTSImport`**
Events: `AssignedChannelsChangedEvent`, `TTSImportHardwareScanFinishedEvent`, `TTSImportReadFileStatusEvent`, `EIDMappingEvent`, `TTSImportSavedChangesStatusEvent`, `TTSImportTestSetupChangedEvent`, `RaiseNotification`, `BusyIndicatorChangeNotification`.
- **`DTS.Common.Interface.TestSetups.Imports.TTS.*`**
Interfaces: `IDigitalOutputChannelsView`, `IDigitalInputChannelsView`, `ITOMChannelsView`, `ILevelTriggerView`, `IDigitalOutputChannelsViewModel`, `IDigitalInputChannelsViewModel`, `ITOMChannelsViewModel`, `ILevelTriggerViewModel`.
- **`DTS.Common.Interface.DataRecorders`**
Interfaces: `IDASHardware`, `IHardwareChannel`.
- **`DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile`**
Interfaces: `ITTSSetup`, `ITTSChannelRecord`.
- **`TTSImport.Model`**
Classes: `DASChannel`, `TTSChannelRecord`.
- **`TTSImport.Resources`**
Static resources: `StringResources` (e.g., `Analog_Enable`, `AssignSensorPrompt`).
- **`Prism.Events`**
`IEventAggregator`, `PubSubEvent<T>`.
- **`Prism.Regions`**
`IRegionManager`.
- **`Unity`**
`IUnityContainer`.
- **`Prism.Commands`**
`DelegateCommand`.
- **`DTS.Common.DAS.Concepts`**
`DASChannel` (in `LevelTriggerViewModel`).
- **`DTS.Common.Enums`**
`ExcitationVoltageOptions`, `DigitalInputModes`.
- **`DTS.DASLib.Service`**
Referenced in `TOMChannelsViewModel` (no direct usage in provided code).
### External Dependencies
- **WPF (`System.Windows`, `System.Windows.Data`)**
Used for `ICollectionView`, `CollectionViewSource`, `Dispatcher`, `MessageBox`.
- **.NET Core/Standard libraries**
`System.Collections.ObjectModel`, `System.ComponentModel`, `System.Threading.Tasks`, `System.Linq`.
### Inferred Usage
- **`DigitalOutputChannelsViewModel`** is used when configuring digital output channels after hardware scan and EID mapping.
- **`DigitalInputChannelsViewModel`** and **`TOMChannelsViewModel`** are used for interactive assignment of unassigned channels to hardware, with similar UI patterns.
- **`LevelTriggerViewModel`** is used for level trigger configuration and relies on `TTSImportReadFileStatusEvent` and `TTSImportSavedChangesStatusEvent` to trigger `UpdateLevelTriggers()`.
- All view models depend on `AssignedChannelsChangedEvent` to refresh channel lists when assignments change elsewhere in the system.
## 5. Gotchas
- **`IsDirty` is never set to `true`** — it is declared but unused. Any change detection must be handled externally (e.g., via `TTSImportTestSetupChangedEvent`).
- **`Cleanup()` and `Initialize()` methods are no-ops** — no resource cleanup or initialization logic is implemented in these methods.
- **`LevelTriggers` is read-only** — `LevelTriggerViewModel` does not support creating or deleting level triggers; it only exposes existing ones.
- **`TOMChannelsViewModel` assumes squib channels are paired** — it iterates hardware channels in steps of 2 (`i += 2`) to select squib channels, which may not hold if hardware layout changes.
- **`DigitalInputChannelsViewModel` and `TOMChannelsViewModel` use `SelectedRemainingChannel` and `SelectedDASChannel` to control button states**, but selection changes may not trigger `DetermineRemoveEnableStatus()` if not handled via property setters (e.g., programmatic selection may require manual `OnPropertyChanged`).
- **`AssignWork()` in `DigitalInputChannelsViewModel` and `TOMChannelsViewModel` modifies `RemainingChannels` and `DASChannels` collections directly**, which may cause UI flicker or require `CollectionViewSource.GetDefaultView(...).Refresh()` to update.
- **`OnAssignedChannelsChangedEvent` in `DigitalOutputChannelsViewModel` creates new `TTSChannelRecord` instances for unassigned channels**, but does not add them to `_setup.Channels` — only the `DASChannel` is updated. This may lead to inconsistencies if `_setup.Channels` is expected to be authoritative.
- **`OnEIDComplete` in `DigitalOutputChannelsViewModel` inverts the sensor-to-channel mapping**, but only if the input dictionary is non-empty. If empty, `_hardwareChannelIdToSensorId` remains an empty dictionary.
- **`VoltageIsValid` in `LevelTriggerViewModel` catches all exceptions from `GetExcitationVoltageEnumFromMagnitude`**, which may hide invalid voltage inputs (e.g., negative or unsupported values).
- **`DigitalInputChannelsViewModel` and `TOMChannelsViewModel` use `MessageBox.Show` for confirmation prompts**, which is synchronous and may block the UI thread. The use of `Task.Run` around `MessageBox.Show` is unnecessary and misleading (UI calls must be on the UI thread).
- **`EnableOrDisableText` uses `StringResources.Analog_Enable` and `StringResources.Analog_Disable`** — misleading naming for digital channels.
- **`DASChannel.EID` is only set if the hardware channel ID exists in `_hardwareChannelIdToSensorId`** — if the mapping is incomplete, EID may be missing even if a sensor is physically present.
- **No validation is performed on `SelectedDASChannel` or `SelectedRemainingChannel` before assignment** — null checks are present in command handlers but not in property setters.
- **`LevelTriggerViewModel` does not expose `DASChannels` or `RemainingChannels`** — it only exposes `LevelTriggers`, making it impossible to view or edit channel assignments directly in this view model.