--- source_files: - DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/ViewModel/GraphViewModel.cs generated_at: "2026-04-16T11:13:10.472796+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "cd4107fac05f80cd" --- # GraphViewModel Documentation ## 1. Purpose `GraphViewModel` is the ViewModel component for the Graph module within the DTS Viewer application. It serves as the mediator between the graph view (`IGraphView`) and the underlying data layer, managing chart visualization state, handling user notifications, and coordinating event-driven communication with parent ViewModels. The class supports multiple initialization contexts—either as a child of `IViewerMainViewModel` or `IPSDReportMainViewModel`—with different subscription behaviors and UI configurations based on the context (e.g., "DataSelect" mode vs. default/result mode). --- ## 2. Public Interface ### Constructor ```csharp public GraphViewModel(IGraphView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer) ``` Initializes the ViewModel with its associated view, region manager for navigation, event aggregator for pub/sub messaging, and Unity container for dependency resolution. Sets the view's `DataContext` to itself and instantiates interaction requests. ### Properties | Property | Type | Access | Description | |----------|------|--------|-------------| | `View` | `IGraphView` | get; private set | The associated graph view instance. | | `DataSeriesView` | `ITestDataSeriesView` | get; set | The data series view used for chart rendering. | | `NotificationRequest` | `InteractionRequest` | get; private set | Interaction request for displaying notifications. | | `ConfirmationRequest` | `InteractionRequest` | get; private set | Interaction request for displaying confirmations (shadows base member). | | `ContextGraphRegion` | `object` | get; set | Gets/sets the content of the `GraphRegion` on the view; raises `OnPropertyChanged` on set. | | `MessageText` | `string` | get; set | Status message text; default is `"Please select Event(s) to export data"`. | | `MessageVisibility` | `bool` | get; set | Controls visibility of the message panel; triggers `FireVisibilities()` on set. | | `ProgressPercent` | `double` | get; set | Progress percentage for loading operations; default `0D`. | | `ProgressText` | `string` | get; set | Progress status text; default `"Reading channel data..."`. | | `ProgressVisibility` | `bool` | get; set | Controls visibility of progress indicators; triggers `FireVisibilities()` on set. | | `GraphInfoVisibility` | `bool` | get; set | Controls visibility of graph info panel; triggers `FireVisibilities()` on set. | | `GraphVisibility` | `bool` | get | Computed as `!MessageVisibility`. | | `HeaderInfo` | `string` | get | Returns `"GraphRegion"`. | | `IsBusy` | `bool` | get; set | Busy state indicator (shadows base member). | | `IsDirty` | `bool` | get | Always returns `false` (shadows base member). | ### Methods ```csharp public override void Initialize() ``` Empty override; no behavior. ```csharp public override void Initialize(object parameter) ``` Primary initialization logic. Behavior depends on `parameter` type: - **If `IViewerMainViewModel`**: Calls `Subscribe()` and sets `Parent` and `DataSeriesView`. - **If `Tuple` where `Item1` is `IPSDReportMainViewModel`**: Calls `SubscribeDataSelect()` or `SubscribeResult()` based on `Item2` value (`"DataSelect"` vs. default). Configures chart scrollbars and actions based on mode. ### Events ```csharp public new event PropertyChangedEventHandler PropertyChanged ``` Shadows base `PropertyChanged` event; raised via `OnPropertyChanged(string)`. --- ## 3. Invariants 1. **Parent Matching**: Event handlers `OnTestSelectedCountChanged` and `OnGraphSelectedCountChanged` will early-return if `Parent != arg.ParentVM` or `Parent != arg?.ParentVM` respectively. 2. **GraphVM Identity Check**: `OnGraphChannelsReadCompleted` and `OnGraphChannelReadCalcProgressChangedEvent` require `this == arg.GraphVM` to proceed. 3. **Null Argument Handling**: `OnGraphChannelsReadCompleted` returns immediately if `arg` is null. 4. **Progress Bounds**: `ProgressPercent` is only updated if `arg.ProgressPercent >= 0`. 5. **Visibility Relationships**: `GraphVisibility` is always the logical inverse of `MessageVisibility`. 6. **Initialization Contract**: `Initialize(object parameter)` expects either `IViewerMainViewModel` or a specific `Tuple` pattern; other types result in no initialization. --- ## 4. Dependencies ### This Module Depends On: - **C1.WPF.C1Chart** - ComponentOne charting library (used for `AxisScrollBar` type casting) - **DTS.Common.Base** - `BaseViewModel`, `IBaseViewModel`, `IBaseModel` - **DTS.Common.Events** - Event types: `RaiseNotification`, `GraphSelectedChannelCountNotification`, `TestSummaryCountNotification`, `TestModificationChangedEvent`, `GraphChannelsReadCompletedNotification`, `GraphChannelReadCalcProgressChangedEvent` - **DTS.Common.Interactivity** - `InteractionRequest`, `Notification`, `Confirmation` - **DTS.Common.Interface** - `IGraphViewModel`, `IGraphView`, `ITestDataSeriesView`, `ITestDataSeriesViewModel`, `ITestModificationModel`, `IViewerMainViewModel`, `IPSDReportMainViewModel` - **Prism.Events** - `IEventAggregator`, `ThreadOption` - **Prism.Regions** - `IRegionManager` - **Unity** - `IUnityContainer` ### Concrete Type Dependencies (Internal): - `GraphView` - Referenced in `ContextGraphRegion` property - `TestDataSeriesView` - Referenced in `Initialize()` for chart configuration - `TestDataSeriesViewModel` - Referenced in `GetTestDataSeriesView()` for PSD subscription --- ## 5. Gotchas 1. **Shadowed Base Members**: Multiple members use the `new` keyword to shadow base class implementations (`PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`, `ConfirmationRequest`, `Model`). This may cause unexpected behavior if consumers interact through base class references. 2. **Code Duplication**: `Subscribe()`, `SubscribeDataSelect()`, and `SubscribeResult()` have nearly identical implementations. The only difference is that `Subscribe()` additionally subscribes to `TestModificationChangedEvent`, but the handler `OnTestModificationChanged` is empty. 3. **Empty Handler**: `OnTestModificationChanged(ITestModificationModel obj)` has no implementation—potential tech debt or placeholder. 4. **Concrete Type Casting**: The code directly casts to `GraphView` and `TestDataSeriesView` concrete types, breaking the abstraction provided by interfaces. This creates tight coupling and could cause runtime failures if different implementations are registered. 5. **Unused Private Field**: `Model` property is declared but never used (suppressed by `// ReSharper disable NotAccessedField.Local`). 6. **Hardcoded Strings**: Chart type comparison uses literal strings (`"DataSelect"`, `"Graph"`) without constants, risking typos. 7. **Thread Affinity**: `GraphChannelsReadCompletedNotification` and `GraphChannelReadCalcProgressChangedEvent` are explicitly subscribed with `ThreadOption.UIThread`, indicating UI updates must occur on the dispatcher thread.