--- source_files: - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/ViewModel/TestModificationViewModel.cs generated_at: "2026-04-16T13:45:56.000728+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "297454e79e1ccbbd" --- # Documentation: TestModificationViewModel ## 1. Purpose `TestModificationViewModel` is a Prism-based ViewModel that manages the test modification UI panel in the DTS Viewer application. It enables users to modify test data properties (T0 timing, sensitivity, line fit, descriptions, EU multipliers/offsets, filters, and data flags) for selected channels. The class coordinates between the UI, a sensor calibration database, and the broader application via event aggregation, while enforcing permission-based edit controls and providing undo/redo capabilities for modifications. --- ## 2. Public Interface ### Constructor ```csharp public TestModificationViewModel( ITestModificationView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer) ``` Initializes the ViewModel, sets up the View's DataContext, creates interaction requests, and subscribes to four events: `RaiseNotification`, `GraphSelectedChannelsNotification`, `ShiftT0Event`, and `SetUseZeroForUnfilteredEvent`. ### Properties | Property | Type | Description | |----------|------|-------------| | `View` | `ITestModificationView` | Gets/sets the associated view instance. | | `Parent` | `IBaseViewModel` | Gets/sets the parent ViewModel reference. | | `Model` | `TestModificationModel` | The model containing channel modification state. Setting updates the model's `Parent` reference. | | `PreviewCommand` | `DelegateCommand` | Executes `PreviewMethod()` to preview line fit changes. | | `WriteCommand` | `DelegateCommand` | Executes `WriteMethod()` to persist modifications after validation and user confirmation. | | `UndoCommand` | `DelegateCommand` | Executes `UndoMethod()` to revert the last modification. | | `UndoAllCommand` | `DelegateCommand` | Executes `UndoAllMethod()` to revert all modifications. | | `TestModificationVisability` | `bool` | Controls visibility of the modification panel; true only when exactly one channel is selected. | | `IsBackedUp` | `bool` | Indicates whether a backup exists for the current model state. Private setter. | | `UseISOCodeFilterMapping` | `bool` | When true, forces ISOCode field filter to match channel's SoftwareFilter. Defaults to `false`. | | `UseZeroForUnfiltered` | `bool` | Gets/sets whether to use zero for unfiltered values. Set via `SetUseZeroForUnfilteredEvent`. | | `IsFilterEnabled` | `bool` | Gets/sets filter enabled state with property change notification. | | `HeaderInfo` | `string` | Returns `"TestSummaryRegion"`. | | `IsBusy` | `bool` | Busy indicator with property change notification. | | `IsDirty` | `bool` | Dirty state flag. | | `IsNavigationIncluded` | `bool` | Navigation inclusion flag. | | `NotificationRequest` | `InteractionRequest` | Interaction request for notifications. | | `ConfirmationRequest` | `InteractionRequest` | Interaction request for confirmations. | ### Methods ```csharp public void UpdateDatabaseMethod() ``` Updates calibration in the database. Sets `CalibrationId = -1`, updates `ModifyDate` to `DateTime.Now`, creates a new `SensorCalibration`, inserts via `DbOperations.SensorCalibrationsInsert()`, then refreshes `Model.Cal` from latest database record. Publishes `PageErrorEvent` on failure. ```csharp public override void Initialize() ``` Empty override. ```csharp public override void Initialize(object parameter) ``` Sets `Parent` to the provided parameter cast as `IBaseViewModel`. ```csharp public void PublishChanges() ``` If not populating and `Model.IsModifiedDataFlag` is true, immediately saves the data flag modification and updates `IsBackedUp`. Always publishes `TestModificationChangedEvent` with the current model. --- ## 3. Invariants 1. **Single-Channel Selection**: `TestModificationVisability` is `true` only when `channels.Count == 1 && channels.Count(x => x.IsSelected) == 1`. Multi-channel or no selection disables the modification panel. 2. **T0 Validation**: T0 shifts are validated via `Model.ValidateT0()` before write operations. T0 cannot shift beyond the dataset bounds (addresses case #14661). 3. **Calibration Sorting**: Calibration records are sorted in ascending order by `CalibrationDate`, then by `ModifyDate` as a tiebreaker (see `CompareCalibrations`). 4. **Analog Sensor Calibration Display**: Calibrations are only displayed for sensors where `SensorType == 0` (analog sensors). 5. **Permission-Based Controls**: Edit permissions (`EnableSensitivityControl`, `EnableLineFitControl`, `EnableDescriptionControl`, `EnableEUMultiplierControl`, `EnableEUOffsetControl`, `EnableFilterControl`, `IsT0Enabled`, `IsDataFlagEnabled`) are gated by `IViewerMainViewModel.DoesUserHaveEditPermission`. 6. **Population Guard**: The static `IsPopulating` flag prevents `PublishChanges()` from executing data flag saves during model population. --- ## 4. Dependencies ### This Module Depends On: - `DTS.Common.Base` (`BaseViewModel`) - `DTS.Common.Events` (`PageErrorEvent`, `PageErrorArg`, `ShiftT0Event`, `ShiftT0EventArguments`, `TestModificationChangedEvent`, `ShowT0CursorEvent`, `GraphSelectedChannelsNotification`, `GraphSelectedChannelsNotificationArg`, `RaiseNotification`, `SetUseZeroForUnfilteredEvent`) - `DTS.Common.Interactivity` (`Notification`, `Confirmation`, `NotificationContentEventArgs`, `InteractionRequest`) - `DTS.Common.Interface` (`IBaseViewModel`, `IViewerMainViewModel`) - `DTS.Common.Interface.Sensors` (`ISensorDbRecord`, `ISensorCalDbRecord`) - `DTS.Common.Settings` (`SettingsDB`, `Keys`) - `DTS.Common.Storage` (implied via `DbOperations`) - `DTS.Common.Utilities.Logging` (`APILogger`) - `DTS.SensorDB` (`DbOperations`, `SensorCalibration`) - `DTS.Viewer.ChartOptions.Model` (channel types) - `DTS.Viewer.TestModification.Model` (`TestModificationModel`, `TestModelManipulation`) - `Prism.Commands` (`DelegateCommand`) - `Prism.Events` (`IEventAggregator`) - `Prism.Regions` (`IRegionManager`) - `Unity` (`IUnityContainer`) ### What Depends On This Module: - `ITestModificationView` (the associated View) - `ITestModificationViewModel` (interface consumers) - Event subscribers to `TestModificationChangedEvent` --- ## 5. Gotchas 1. **Typo in Property Name**: `TestModificationVisability` is misspelled (should be "Visibility"). This is a historical naming quirk. 2. **Silent Exception Swallowing**: `GetLatestCalibration()` catches all exceptions and returns `null` without logging. The comment explicitly states: "there's no access to APILogger here, so rather than adding a reference, just eat the error." 3. **Malformed XML Comment**: The `` tag for `GetLatestCalibration` is not properly closed (uses `` instead of ``). 4. **Base Member Hiding**: Multiple properties (`Model`, `IsBusy`, `IsDirty`, `IsNavigationIncluded`, `PropertyChanged`, `OnPropertyChanged`) use the `new` keyword to hide base class members, which may indicate design issues or legacy refactoring. 5. **Static `IsPopulating` Flag**: The `IsPopulating` property is static, meaning it is shared across all instances of `TestModificationViewModel`. This could cause unexpected behavior if multiple instances exist. 6. **Hardcoded CalibrationId**: `UpdateDatabaseMethod()` sets `CalibrationId = -1` before insertion. The significance of `-1` is not documented in source. 7. **Database Setting Fallback**: `UseISOCodeFilterMapping` defaults to `false` but is retrieved from settings in `WriteMethod()` with a default of `true` via `SettingsDB.GetGlobalValueBool("UseISOCodeFilterMapping", true)`. The property default and settings default are inconsistent. 8. **Null Check Inconsistency**: Some null checks use `null == sensor` style while others use `sensor == null` (likely ReSharper-generated variations).