Files

114 lines
7.1 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
---
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<Notification>` | get; private set | Interaction request for displaying notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | 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<IBaseViewModel, string>` 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<IBaseViewModel, string>` 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<T>`, `IBaseViewModel`, `IBaseModel`
- **DTS.Common.Events** - Event types: `RaiseNotification`, `GraphSelectedChannelCountNotification`, `TestSummaryCountNotification`, `TestModificationChangedEvent`, `GraphChannelsReadCompletedNotification`, `GraphChannelReadCalcProgressChangedEvent`
- **DTS.Common.Interactivity** - `InteractionRequest<T>`, `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.