Files
DP44/enriched-partialglm/DTS Viewer/DTS.Viewer/Modules/Main/ViewModel.md

271 lines
15 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
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-16T11:26:44.035903+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ab73d8a45f8ea2f6"
---
# DTS Viewer Main Module ViewModels Documentation
## 1. Purpose
This module contains the core ViewModel classes for the DTS Viewer application's main shell and primary views. It implements the MVVM pattern using Microsoft Prism and Unity IoC container. The module orchestrates region management, event aggregation for cross-component communication, and view composition for the main application shell, standard viewer mode, and export-focused mode. The ViewModels serve as the presentation logic layer, binding views to data, handling user interactions via commands, and coordinating child view instantiation within named UI regions.
---
## 2. Public Interface
### ViewerShellViewModel
**Location:** `DTS.Viewer.Modules.Main.ViewModel`
**Class Declaration:**
```csharp
[Export(typeof(IShellView))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ViewerShellViewModel : NotificationObject, IViewerShellViewModel
```
**Constructor:**
```csharp
public ViewerShellViewModel(IViewerShellView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the shell view model, sets the View's DataContext, creates interaction requests, subscribes to `RaiseNotification` events, and registers `IMainView`/`MainView` and `IMainViewModel`/`MainViewModel` with the Unity container.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IViewerShellView` | Gets the associated shell view |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for notification dialogs |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for confirmation dialogs |
| `ContextMainRegion` | `Object` | Gets/sets the content of the MainRegion |
| `IsMenuIncluded` | `bool` | Indicates whether menu is included |
| `IsNavigationIncluded` | `bool` | Indicates whether navigation is included |
| `HeaderInfo` | `string` | Returns `"MainRegion"` |
| `IsBusy` | `bool` | **Throws `NotImplementedException`** |
| `IsDirty` | `bool` | **Throws `NotImplementedException`** |
**Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `void Initialize()` | Stub implementation (sets local `i = 10`) |
| `Initialize` | `void Initialize(object parameter)` | Stub implementation (sets local `i = 22`) |
| `Initialize` | `void Initialize(object parameter, object model)` | Empty stub |
| `Activated` | `void Activated()` | Empty stub |
| `Cleanup` | `void Cleanup()` | **Throws `NotImplementedException`** |
| `CleanupAsync` | `Task CleanupAsync()` | **Throws `NotImplementedException`** |
| `InitializeAsync` | `Task InitializeAsync()` | **Throws `NotImplementedException`** |
| `InitializeAsync` | `Task InitializeAsync(object parameter)` | **Throws `NotImplementedException`** |
| `GetRegions` | `List<FrameworkElement> GetRegions()` | Returns all elements named "Region" in the MainShell |
| `OnRaiseNotification` | `void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)` | Private handler that raises `NotificationRequest` with transformed args |
---
### MainViewModel
**Location:** `DTS.Viewer.Modules.Main.ViewModel`
**Class Declaration:**
```csharp
public class MainViewModel : BaseViewModel<IMainViewModel>, IMainViewModel
```
**Constructor:**
```csharp
public MainViewModel(IMainView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the view model, sets DataContext, creates interaction requests, and subscribes to `RaiseNotification` event.
**Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `override void Initialize()` | Empty override |
| `Initialize` | `override void Initialize(object parameter)` | Sets `Parent`, propagates menu/navigation flags, subscribes to `AssemblyListNotification` and `BusyIndicatorChangeNotification` events |
| `Activated` | `override void Activated()` | Empty override |
| `GetRegions` | `List<FrameworkElement> GetRegions()` | Returns all elements named "Region" in MainShell |
**Private Methods:**
| Method | Description |
|--------|-------------|
| `OnAssemblyListChange(AssemblyListInfo e)` | Processes assembly custom attributes ending with "ImageAttribute", creates `AssemblyNameImage` objects, and populates regions based on `eAssemblyRegion` enum |
| `OnRaiseNotification(NotificationContentEventArgs)` | Raises `NotificationRequest` with transformed content |
| `OnBusyIndicatorNotification(bool eventArg)` | Sets `IsBusy` property |
| `GetNavigationView(IBaseViewModel)` | Resolves and initializes `INavigationView`/`INavigationViewModel` |
| `GetPropertyView(IBaseWindowModel)` | Resolves and initializes `IPropertyView`/`IPropertyViewModel` |
| `GetGraphView(IBaseWindowModel)` | Resolves and initializes `IGraphView`/`IGraphViewModel` |
**Region Context Properties:**
| Property | Region Name |
|----------|-------------|
| `ContextNavigationRegion` | NavigationRegion |
| `ContextGraphRegion` | GraphRegion |
| `ContextTestsRegion` | TestsRegion |
| `ContextGraphsRegion` | GraphsRegion |
| `ContextLegendRegion` | LegendRegion |
| `ContextDiagRegion` | DiagRegion |
| `ContextStatsRegion` | StatsRegion |
| `ContextCursorRegion` | CursorRegion |
| `ContextPropertyRegion` | PropertyRegion |
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IBaseView` | The associated view |
| `IsBusy` | `bool` | Busy indicator state |
| `IsBusyMessage` | `string` | Message for busy indicator |
| `IsMenuIncluded` | `bool` | Menu inclusion flag |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag |
| `HeaderInfo` | `string` | Returns `"MainRegion"` |
---
### ExportMainViewModel
**Location:** `DTS.Viewer.Modules.Main.ViewModel`
**Class Declaration:**
```csharp
public class ExportMainViewModel : BaseViewModel<IExportMainViewModel>, IExportMainViewModel
```
**Constructor:**
```csharp
public ExportMainViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes interaction requests, resolves `IExportMainViewGrid` as the View, and sets DataContext.
**Key Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IBaseView` | Gets/sets the view (resolved as `IExportMainViewGrid`) |
| `Standalone` | `bool` | Determines whether to use `ExportMainView` or `ExportMainViewGrid` |
| `SelectedTest` | `string` | Currently selected test |
| `SelectedDTSFile` | `string` | Currently selected DTS file |
| `SelectedEventList` | `List<ITestEvent>` | List of selected test events |
| `AvailableTestIds` | `List<string>` | Available test IDs |
| `SettingsVisibility` | `Visibility` | Controls settings panel visibility |
| `ActiveContent` | `IBaseViewModel` | Currently active content |
| `TotalSelectedTests` | `int` | Count of selected tests |
| `TotalLoadedTests` | `int` | Count of loaded tests |
| `TotalSelectedGraphs` | `int` | Count of selected graphs |
| `TotalLoadedGraphs` | `int` | Count of loaded graphs |
| `SelectedDataFolder` | `string` | Selected data folder path |
| `SelectedDataFile` | `string` | Selected data file |
| `ShowModifications` | `bool` | Indicates if modifications should be shown |
| `ChannelCodeViewMode` | `IsoViewMode` | Channel code display mode (default: `IsoViewMode.ISOAndUserCode`) |
| `CalibrationBehaviorSetting` | `CalibrationBehaviors` | Calibration behavior (default: `CalibrationBehaviors.NonLinearIfAvailable`) |
| `CalibrationBehaviorSettableInViewer` | `bool` | Whether calibration behavior is settable (default: `true`) |
| `DoesUserHaveEditPermission` | `bool` | User edit permission flag (default: `false`) |
| `ConfigPath` | `string` | Configuration path |
| `IsBusy` | `bool` | Busy indicator state |
| `IsBusyMessage` | `string` | Busy indicator message |
| `IsMenuIncluded` | `bool` | Menu inclusion flag |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag |
| `HeaderInfo` | `string` | Returns `"MainRegion"` |
**Commands:**
| Command | CanExecute Condition | Action |
|---------|---------------------|--------|
| `LoadLayoutCommand` | `File.Exists(@".\DataProViewerAvalonDock.config")` | Deserializes AvalonDock layout from config file |
| `SaveLayoutCommand` | Always `true` | Serializes AvalonDock layout to `.\AvalonDock.config` |
**Public Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `override void Initialize()` | Calls `Subscribe()` to register event handlers |
| `Initialize` | `override void Initialize(object parameter)` | Sets `Parent`, propagates flags, calls `Subscribe()` |
| `Activated` | `override void Activated()` | Empty override |
| `AddSelectedEvents` | `void AddSelectedEvents(string groupName, List<ITestEvent> events)` | Adds events to `SelectedEventList`, publishes busy indicator events |
| `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 `-1` step |
| `RightKeyPress` | `void RightKeyPress()` | Publishes `ShiftT0Event` with `+1` step |
| `GetRegions` | `List<FrameworkElement> GetRegions()` | Returns regions based on `Standalone` mode |
**Private Event Handlers:**
| Method | Event Subscribed |
|--------|-----------------|
| `OnDataFileSelected` | `DataFileSelectedEvent` |
| `OnViewerSettingsVisibilityChanged` | `ViewerSettingsVisibilityChangedEvent` |
| `OnGraphLoadedCountChanged` | `GraphLoadedCountNotification` |
| `OnGraphSelectedCountChanged` | `GraphSelectedEventCountNotification` |
| `OnGraphChannelsReadCompleted` | `GraphChannelsReadCompletedNotification` (UIThread) |
| `OnTestLoadedChanged` | `TestLoadedCountNotification` |
| `OnTestSelectedCountChanged` | `TestSummaryCountNotification` |
| `OnLoadExportModule` | `LoadExportModuleEvent` |
| `OnShiftT0Event` | `ShiftT0Event` |
| `OnSaveToPDFRequested` | `SaveToPDFRequestedEvent` |
**View Factory Methods:**
| Method | Returns |
|--------|---------|
| `GetGraphView(IBaseViewModel)` | `IGraphView` with initialized `IGraphViewModel` |
| `GetGraphListView(IBaseViewModel)` | `IExportGraphMainView` with initialized `IExportGraphMainViewModel` |
| `GetTestDefinitionView(IBaseViewModel)` | `ITestSummaryListView` with initialized `ITestSummaryListViewModel` |
---
## 3. Invariants
1. **View-ViewModel Binding**: Each ViewModel sets `View.DataContext = this` in its constructor, establishing the binding invariant.
2. **Region Content Access**: All `ContextXxxRegion` properties cast the `View` to a concrete type (`MainView`, `ViewerShellView`, `ExportMainView`, or `ExportMainViewGrid`) before accessing region content. The view must be of the expected type.
3. **Parent Parameter Type**: In `MainViewModel.Initialize(object parameter)` and `ExportMainViewModel.Initialize(object parameter)`, the parameter is cast to `IBaseWindowModel` without type checking.
4. **Standalone Mode Switching**: `ExportMainViewModel` requires `Standalone` to be set correctly before accessing region properties, as it determines whether to cast to `ExportMainView` or `ExportMainViewGrid`.
5. **Event Subscription Pattern**: ViewModels subscribe to events in constructors or `Initialize` methods; unsubscribing is not visible in the source.
6. **Property Change Notification**: All setters that modify bound properties call `OnPropertyChanged(string)` with the property name.
7. **Unity Container Registration**: `ViewerShellViewModel` registers `IMainViewModel` with `ContainerControlledLifetimeManager`, making it a singleton.
---
## 4. Dependencies
### External Dependencies (from imports):
- `Microsoft.Practices.Prism.Events` - `IEventAggregator`, `ThreadOption`
- `Microsoft.Practices.Prism.Interactivity.InteractionRequest` - `InteractionRequest<T>`, `Notification`, `Confirmation`
- `Microsoft.Practices.Prism.Regions` - `IRegionManager`
- `Microsoft.Practices.Prism.ViewModel` - `NotificationObject`
- `Microsoft.Practices.Unity` - `IUnityContainer`, `ContainerControlledLifetimeManager`
- `System.ComponentModel.Composition` - `[Export]`, `[PartCreationPolicy]`, `CreationPolicy`
- `Xceed.Wpf.AvalonDock.Layout.Serialization` - `XmlLayoutSerializer` (ExportMainViewModel only)
- `Prism.Events` - Used in ExportMainViewModel alongside older Prism namespace
- `Prism.Regions` - Used in ExportMainViewModel alongside older Prism namespace
- `Unity` - Used in ExportMainViewModel alongside older Unity namespace
### Internal Dependencies:
- `DTS.Common.Base` - `BaseViewModel<T>`, `IBaseViewModel`, `IBaseView`, `IBaseWindowModel`
- `DTS.Common.Events` - Event types: `RaiseNotification`, `AssemblyListNotification`, `BusyIndicatorChangeNotification`, `DataFolderChangedEvent`, `LoadExportModuleEvent`, `TestLoadedCountNotification`, `TestSummaryCountNotification`, `GraphLoadedCountNotification`, `ShiftT0Event`, `GraphSelectedEventCountNotification`, `GraphChannelsReadCompletedNotification`, `ViewerSettingsVisibilityChangedEvent`, `DataFileSelectedEvent`, `SaveToPDFRequestedEvent`, `ChannelCodesViewChangedEvent`, `ExportCalibrationBehaviorSettingChangedEvent`, `CalibrationBehaviorSettableInViewerChangedEvent`, `ResetZoomChangedEvent`, `PageErrorEvent`
- `DTS.Common.Interface` - Various view/viewmodel interfaces: `IMainView`, `IMainViewModel`, `IViewerShellView`, `IViewerShellViewModel`, `INavigationView`, `INavigationViewModel`, `IPropertyView`, `IPropertyViewModel`, `IGraphView`, `IGraphViewModel`, `IExportMainViewGrid`, `IExportMainViewModel`, `IExportGraphMainView`, `IExportGraphMainViewModel`, `ITestSummaryListView`, `ITestSummaryListViewModel`, `ITestEvent`
- `DTS.Common.Utils` - `Utils.GetChildrenByName()`
- `DTS.Common.Enums` - `eAssemblyRegion`
- `DTS.Common.Enums.Sensors` - `IsoViewMode`, `CalibrationBehaviors`
- `DTS.Common.Classes.Viewer.Commands` - `RelayCommand`
- `DTS.Common.Interactivity` - (imported but usage unclear)
- `DTS.Viewer.Resources` - `StringResources`
### View Dependencies (referenced but not provided):
- `ViewerShellView`, `MainView`, `ExportMainView`, `ExportMainViewGrid`
---
## 5. Gotchas
1. **NotImplementedException Throwing Members**: `ViewerShellViewModel` has multiple members that throw `NotImplementedException`:
- `IsBusy` getter
- `IsDirty` getter
- `Cleanup()`
- `CleanupAsync()`
- `InitializeAsync()`
- `InitializeAsync(object parameter)`
These appear to be interface implementations that were never completed. Calling code must avoid these.
2. **Unused Local Variables**: `ViewerShellViewModel.Initialize()` methods set local `int i` variables that are never used—likely debug stubs.
3. **Duplicate DataContext Assignment**: `ExportMainViewModel` constructor sets `View.DataContext = this` twice