Files
2026-04-17 14:55:32 -04:00

192 lines
15 KiB
Markdown

---
source_files:
- DTS Viewer/DTS.Viewer/Modules/Main/ViewModel/ViewerShellViewModel.cs
- DTS Viewer/DTS.Viewer/Modules/Main/ViewModel/MainViewModel.cs
- DTS Viewer/DTS.Viewer/Modules/Main/ViewModel/ExportMainViewModel.cs
generated_at: "2026-04-16T14:05:37.474639+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ab73d8a45f8ea2f6"
---
# DTS Viewer Main Module View Models Documentation
## 1. Purpose
This module contains the core view models for the DTS Viewer application's main shell and content regions. It implements the MVVM pattern using Microsoft Prism and Unity IoC to manage view composition, region navigation, and event-driven communication. The three view models form a hierarchy: `ViewerShellViewModel` serves as the application shell container, `MainViewModel` manages primary content regions (graphs, properties, navigation), and `ExportMainViewModel` extends functionality for data export, PDF generation, and layout persistence.
---
## 2. Public Interface
### ViewerShellViewModel
**Signature:** `public class ViewerShellViewModel : NotificationObject, IViewerShellViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ViewerShellViewModel(IViewerShellView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes the shell, sets up notification requests, subscribes to `RaiseNotification` events, and registers `IMainView`/`IMainViewModel` types with Unity. |
| View | `IViewerShellView View { get; private set; }` | Gets the associated shell view. |
| NotificationRequest | `InteractionRequest<Notification> NotificationRequest { get; private set; }` | Interaction request for displaying notifications. |
| ConfirmationRequest | `InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }` | Interaction request for displaying confirmations. |
| Initialize | `void Initialize()` | No-op implementation (assigns local variable `i = 10`). |
| Initialize | `void Initialize(object parameter)` | No-op implementation (assigns local variable `i = 22`). |
| Initialize | `void Initialize(object parameter, object model)` | Empty implementation. |
| Activated | `void Activated()` | Called on activation; currently no-op. |
| GetRegions | `List<FrameworkElement> GetRegions()` | Returns all FrameworkElements named "Region" within the MainShell. |
| ContextMainRegion | `Object ContextMainRegion { get; set; }` | Gets/sets the content of the MainRegion. |
| IsMenuIncluded | `bool IsMenuIncluded { get; set; }` | Indicates whether the menu is included in the shell. |
| IsNavigationIncluded | `bool IsNavigationIncluded { get; set; }` | Indicates whether navigation is included in the shell. |
| HeaderInfo | `string HeaderInfo { get; }` | Returns constant string "MainRegion". |
| IsBusy | `bool IsBusy { get; }` | **Throws `NotImplementedException`.** |
| IsDirty | `bool IsDirty { get; }` | **Throws `NotImplementedException`.** |
| Cleanup | `void Cleanup()` | **Throws `NotImplementedException`.** |
| CleanupAsync | `Task CleanupAsync()` | **Throws `NotImplementedException`.** |
| InitializeAsync | `Task InitializeAsync()` | **Throws `NotImplementedException`.** |
| InitializeAsync | `Task InitializeAsync(object parameter)` | **Throws `NotImplementedException`.** |
---
### MainViewModel
**Signature:** `public class MainViewModel : BaseViewModel<IMainViewModel>, IMainViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `MainViewModel(IMainView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes the view model, sets up notification/confirmation requests, and subscribes to `RaiseNotification` event. |
| View | `IBaseView View { get; private set; }` | Gets the associated main view. |
| Initialize | `override void Initialize()` | Empty override. |
| Initialize | `override void Initialize(object parameter)` | Sets `Parent` from parameter, propagates menu/navigation settings to parent, subscribes to `AssemblyListNotification` and `BusyIndicatorChangeNotification` events. |
| Activated | `override void Activated()` | Empty override. |
| GetRegions | `List<FrameworkElement> GetRegions()` | Returns all FrameworkElements named "Region" within the MainShell. |
| ContextNavigationRegion | `object ContextNavigationRegion { get; set; }` | Gets/sets NavigationRegion content. |
| ContextGraphRegion | `object ContextGraphRegion { get; set; }` | Gets/sets GraphRegion content. |
| ContextTestsRegion | `object ContextTestsRegion { get; set; }` | Gets/sets TestsRegion content. |
| ContextGraphsRegion | `object ContextGraphsRegion { get; set; }` | Gets/sets GraphsRegion content. |
| ContextLegendRegion | `object ContextLegendRegion { get; set; }` | Gets/sets LegendRegion content. |
| ContextDiagRegion | `object ContextDiagRegion { get; set; }` | Gets/sets DiagRegion content. |
| ContextStatsRegion | `object ContextStatsRegion { get; set; }` | Gets/sets StatsRegion content. |
| ContextCursorRegion | `object ContextCursorRegion { get; set; }` | Gets/sets CursorRegion content. |
| ContextPropertyRegion | `object ContextPropertyRegion { get; set; }` | Gets/sets PropertyRegion content. |
| IsBusy | `new bool IsBusy { get; set; }` | Gets/sets busy indicator state. |
| IsBusyMessage | `new string IsBusyMessage { get; set; }` | Gets/sets busy indicator message. |
| IsMenuIncluded | `new bool IsMenuIncluded { get; set; }` | Gets/sets menu inclusion flag. |
| IsNavigationIncluded | `new bool IsNavigationIncluded { get; set; }` | Gets/sets navigation inclusion flag. |
| HeaderInfo | `string HeaderInfo { get; }` | Returns constant string "MainRegion". |
---
### ExportMainViewModel
**Signature:** `public class ExportMainViewModel : BaseViewModel<IExportMainViewModel>, IExportMainViewModel`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ExportMainViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)` | Initializes the view model, resolves `IExportMainViewGrid` as the view, and sets up interaction requests. |
| View | `IBaseView View { get; set; }` | Gets/sets the associated view. |
| Standalone | `bool Standalone { get; set; }` | Determines whether to use `ExportMainView` (standalone) or `ExportMainViewGrid` for region access. |
| Initialize | `override void Initialize()` | Calls `Subscribe()` to register event handlers. |
| Initialize | `override void Initialize(object parameter)` | Sets `Parent` from parameter, propagates settings, calls `Subscribe()`. |
| Activated | `override void Activated()` | Empty override. |
| AddSelectedEvents | `void AddSelectedEvents(string groupName, List<ITestEvent> events)` | Adds events to `SelectedEventList`, publishes busy indicator notifications. |
| SelectAndIncludeDataFile | `void SelectAndIncludeDataFile(string value)` | Sets selected data file and publishes `DataFolderChangedEvent`. |
| ZoomReset | `void ZoomReset()` | Publishes `ResetZoomChangedEvent` with `true`. |
| LeftKeyPress | `void LeftKeyPress()` | Publishes `ShiftT0Event` with step `-1`. |
| RightKeyPress | `void RightKeyPress()` | Publishes `ShiftT0Event` with step `+1`. |
| GetRegions | `List<FrameworkElement> GetRegions()` | Returns regions based on `Standalone` mode. |
| LoadLayoutCommand | `ICommand LoadLayoutCommand { get; }` | Loads AvalonDock layout from `.\DataProViewerAvalonDock.config`. |
| SaveLayoutCommand | `ICommand SaveLayoutCommand { get; }` | Saves AvalonDock layout to `.\AvalonDock.config`. |
| ContextNavigationRegion | `object ContextNavigationRegion { get; set; }` | Gets/sets NavigationRegion content (mode-dependent). |
| ContextGraphRegion | `object ContextGraphRegion { get; set; }` | Gets/sets GraphRegion content (mode-dependent). |
| ContextGraphListRegion | `object ContextGraphListRegion { get; set; }` | Gets/sets GraphListRegion content (mode-dependent). |
| ContextTestsRegion | `object ContextTestsRegion { get; set; }` | Gets/sets TestsRegion content (mode-dependent). |
| ContextGraphsRegion | `object ContextGraphsRegion { get; set; }` | Gets/sets GraphsRegion content (mode-dependent). |
| ContextPropertyRegion | `object ContextPropertyRegion { get; set; }` | Gets/sets PropertyRegion content. |
| SelectedEventList | `List<ITestEvent> SelectedEventList { get; set; }` | List of selected test events. |
| SelectedDataFolder | `string SelectedDataFolder { get; set; }` | Selected data folder path; publishes `DataFolderChangedEvent` on set. |
| SelectedDataFile | `string SelectedDataFile { get; set; }` | Selected data file path; publishes `DataFolderChangedEvent` on set. |
| TotalSelectedTests | `int TotalSelectedTests { get; set; }` | Count of selected tests; updates `TitleTests`. |
| TotalLoadedTests | `int TotalLoadedTests { get; set; }` | Count of loaded tests; updates `TitleTests`. |
| TotalSelectedGraphs | `int TotalSelectedGraphs { get; set; }` | Count of selected graphs; updates `TitleTestIDs`. |
| TotalLoadedGraphs | `int TotalLoadedGraphs { get; set; }` | Count of loaded graphs; updates `TitleTestIDs`. |
| ShowModifications | `bool ShowModifications { get; set; }` | Indicates if T0 modifications are shown. |
| ChannelCodeViewMode | `IsoViewMode ChannelCodeViewMode { get; set; }` | Channel code view mode; publishes `ChannelCodesViewChangedEvent`. |
| CalibrationBehaviorSetting | `CalibrationBehaviors CalibrationBehaviorSetting { get; set; }` | Calibration behavior; publishes `ExportCalibrationBehaviorSettingChangedEvent`. |
| CalibrationBehaviorSettableInViewer | `bool CalibrationBehaviorSettableInViewer { get; set; }` | Whether calibration behavior is settable; publishes event and selects graphs tab. |
| SettingsVisibility | `Visibility SettingsVisibility { get; private set; }` | Visibility of settings panel. |
| IsBusy | `new bool IsBusy { get; set; }` | Busy indicator state. |
| IsBusyMessage | `new string IsBusyMessage { get; set; }` | Busy indicator message. |
| HeaderInfo | `string HeaderInfo { get; }` | Returns constant string "MainRegion". |
---
## 3. Invariants
1. **Region Content Consistency**: All `Context*Region` properties directly access the underlying view's region content. The view must be properly initialized before any region access.
2. **Standalone Mode Switching**: In `ExportMainViewModel`, the `Standalone` property determines which view type (`ExportMainView` vs `ExportMainViewGrid`) is used for region access. This must be set before accessing any region properties.
3. **Event Subscription Timing**: Event subscriptions occur in `Initialize()` or `Initialize(object parameter)`. Calling region properties or event-triggering methods before initialization may result in null reference exceptions or missed events.
4. **Parent Parameter Casting**: `MainViewModel.Initialize(object parameter)` and `ExportMainViewModel.Initialize(object parameter)` cast the parameter to `IBaseWindowModel`. Passing an incompatible type will cause a runtime exception.
5. **Assembly Attribute Requirements**: `MainViewModel.OnAssemblyListChange` expects assemblies to have attributes whose type names end with "ImageAttribute" and are castable to `ImageAttribute`.
6. **PDF Save Thread Safety**: `OnSaveToPDFRequested` uses `lock(saveLock)` for thread safety. The view's `SaveToPDF` method must be thread-safe.
7. **Layout File Existence**: `CanLoadLayout` returns `false` if `.\DataProViewerAvalonDock.config` does not exist, preventing command execution.
---
## 4. Dependencies
### External Dependencies (from imports)
| Namespace | Purpose |
|-----------|---------|
| `Microsoft.Practices.Prism.Events` / `Prism.Events` | Event aggregation for pub/sub messaging |
| `Microsoft.Practices.Prism.Regions` / `Prism.Regions` | Region management for view composition |
| `Microsoft.Practices.Prism.ViewModel` | `NotificationObject` base class for INPC |
| `Microsoft.Practices.Prism.Interactivity.InteractionRequest` | Dialog/notification interaction requests |
| `Microsoft.Practices.Unity` / `Unity` | IoC container for dependency injection |
| `System.ComponentModel.Composition` | MEF attributes for component export |
| `Xceed.Wpf.AvalonDock.Layout.Serialization` | Docking layout serialization |
| `DTS.Common.Base` | Base interfaces (`IBaseViewModel`, `IBaseView`, `IBaseWindowModel`) |
| `DTS.Common.Events` | Event types (`RaiseNotification`, `AssemblyListNotification`, etc.) |
| `DTS.Common.Interface` | View/model interfaces |
| `DTS.Common.Utils` | Utility methods (`Utils.GetChildrenByName`) |
| `DTS.Common.Enums` | Enumeration types (`IsoViewMode`, `CalibrationBehaviors`, `eAssemblyRegion`) |
| `DTS.Common.Classes.Viewer.Commands` | `RelayCommand` implementation |
### Internal Dependencies
| Dependent | Dependency | Relationship |
|-----------|------------|--------------|
| `ViewerShellViewModel` | `IViewerShellView`, `ViewerShellView` | View contract and concrete type |
| `ViewerShellViewModel` | `IMainView`, `IMainViewModel`, `MainView`, `MainViewModel` | Registers and creates main content |
| `MainViewModel` | `IMainView`, `MainView` | View contract and concrete type |
| `MainViewModel` | `INavigationView`, `INavigationViewModel` | Creates navigation region content |
| `MainViewModel` | `IPropertyView`, `IPropertyViewModel` | Creates property region content |
| `MainViewModel` | `IGraphView`, `IGraphViewModel` | Creates graph region content |
| `ExportMainViewModel` | `IExportMainViewGrid`, `ExportMainViewGrid`, `ExportMainView` | View contracts and concrete types |
| `ExportMainViewModel` | `IGraphView`, `IGraphViewModel` | Creates graph region content |
| `ExportMainViewModel` | `IExportGraphMainView`, `IExportGraphMainViewModel` | Creates graph list region content |
| `ExportMainViewModel` | `ITestSummaryListView`, `ITestSummaryListViewModel` | Creates test summary region content |
---
## 5. Gotchas
1. **NotImplementedException Methods in ViewerShellViewModel**: The following methods throw `NotImplementedException`: `IsBusy` getter, `IsDirty` getter, `Cleanup()`, `CleanupAsync()`, `InitializeAsync()`, and `InitializeAsync(object parameter)`. These appear to be interface requirements that were never implemented.
2. **Property Hiding with `new` Keyword**: Both `MainViewModel` and `ExportMainViewModel` use `new` to hide base class properties (`IsBusy`, `IsBusyMessage`, `IsMenuIncluded`, `IsNavigationIncluded`, `PropertyChanged`). This can cause unexpected behavior when casting to base types.
3. **Dead Code in Initialize Methods**: `ViewerShellViewModel.Initialize()` and `Initialize(object parameter)` contain assignments to local variables (`int i = 10`, `int i = 22`) that have no effect. This appears to be placeholder/debug code.
4. **Region Property Setter Mismatch**: In `MainViewModel`, `ContextGraphRegion` setter calls `OnPropertyChanged("ContextGraphsRegion")` (note the 's' in Graphs), which does not match the property name. This may cause binding issues.
5. **Standalone Mode View Casting**: `ExportMainViewModel` performs direct casts to either `ExportMainView` or `ExportMainViewGrid` based on `Standalone` flag. If `Standalone` is changed after initial access, cached region content may become invalid.
6. **Event Handler Identity Checks**: Several event handlers (e.g., `OnGraphLoadedCountChanged`, `OnTestLoadedChanged`) check `if (this != arg?.ParentVM) return;`. This means events are only processed if the sender explicitly set the `ParentVM` property to match.
7. **CalibrationBehaviorSettableInViewer Side Effect**: Setting `CalibrationBehaviorSettableInViewer` has a side effect of selecting the graphs tab (`((ExportMainViewGrid)