135 lines
7.8 KiB
Markdown
135 lines
7.8 KiB
Markdown
|
|
---
|
||
|
|
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<Notification>` | Interaction request for notifications. |
|
||
|
|
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | 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<T>`)
|
||
|
|
- `DTS.Common.Events` (`PageErrorEvent`, `PageErrorArg`, `ShiftT0Event`, `ShiftT0EventArguments`, `TestModificationChangedEvent`, `ShowT0CursorEvent`, `GraphSelectedChannelsNotification`, `GraphSelectedChannelsNotificationArg`, `RaiseNotification`, `SetUseZeroForUnfilteredEvent`)
|
||
|
|
- `DTS.Common.Interactivity` (`Notification`, `Confirmation`, `NotificationContentEventArgs`, `InteractionRequest<T>`)
|
||
|
|
- `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 `<summary>` tag for `GetLatestCalibration` is not properly closed (uses `<summary>` instead of `</summary>`).
|
||
|
|
|
||
|
|
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).
|