83 lines
8.4 KiB
Markdown
83 lines
8.4 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/ViewModel/GraphMainViewModel.cs
|
||
|
|
generated_at: "2026-04-16T13:48:30.268564+00:00"
|
||
|
|
model: "zai-org/GLM-5-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "09077834bf97663d"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Documentation: GraphMainViewModel
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
The `GraphMainViewModel` class acts as the presentation logic controller for the Graph List module. It is responsible for transforming raw test summary data into a hierarchical, displayable tree of test channels (`TestChannelsTree`), managing the state of channel selection and locking (e.g., for reporting vs. viewing), and mediating communication between the data layer and the UI via Prism's `IEventAggregator`. It handles the logic for assigning distinct colors to channels, filtering channel lists, and enforcing constraints such as the maximum number of lockable channels.
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### Properties
|
||
|
|
|
||
|
|
* **`IFilterView FilterView`**: Gets the filter view instance associated with this view model.
|
||
|
|
* **`IGraphMainView View`**: Gets or sets the associated view interface.
|
||
|
|
* **`IBaseViewModel Parent`**: Gets or sets the parent view model (used to scope event handling).
|
||
|
|
* **`InteractionRequest<Notification> NotificationRequest`**: Gets the interaction request for displaying notifications.
|
||
|
|
* **`InteractionRequest<Confirmation> ConfirmationRequest`**: Gets the interaction request for displaying confirmations.
|
||
|
|
* **`ObservableCollection<ITestChannel> ChannelList`**: Gets or sets the full list of available channels. Setting this updates `IsFilterEnabled` and resets `FilteredChannelList`.
|
||
|
|
* **`ObservableCollection<ITestChannel> FilteredChannelList`**: Gets or sets the list of channels currently displayed (after filtering). Setting this triggers a rebuild of `TestChannelsTree`.
|
||
|
|
* **`List<ITestChannel> LockedChannelList`**: Gets or sets the list of channels currently locked by the user.
|
||
|
|
* **`List<ITestChannel> SelectedChannelList`**: Gets or sets the list of channels currently selected by the user.
|
||
|
|
* **`ObservableCollection<TreeViewChannels> TestChannelsTree`**: Gets or sets the hierarchical structure of tests, groups, and channels bound to the UI.
|
||
|
|
* **`bool IsFilterEnabled`**: Gets or sets a value indicating whether the filter UI is enabled (true if `ChannelList` has items).
|
||
|
|
* **`string SelectedGroupName`**: Gets or sets the name of the currently selected group.
|
||
|
|
* **`string LockedGroupName`**: Gets or sets the name of the currently locked group.
|
||
|
|
* **`object ContextGraphMainRegion`**: Gets or sets the data context for the `GraphMainRegion` within the view.
|
||
|
|
* **`bool TestModified`**: Gets or sets a value indicating whether the underlying test has been modified.
|
||
|
|
|
||
|
|
### Methods
|
||
|
|
|
||
|
|
* **`void Initialize()`**: Overrides base `Initialize`. Currently empty.
|
||
|
|
* **`void Initialize(object parameter)`**: Overrides base `Initialize`. Sets the `Parent`, determines if locked-only mode is active (if Parent is `IPSDReportMainViewModel`), initializes the `FilterView`, and subscribes to events.
|
||
|
|
* **`void Activated()`**: Overrides base `Activated`. Publishes a `FilterParameterChangedEvent` with an empty parameter to reset the filter.
|
||
|
|
* **`void PublishSelectedChannels()`**: Publishes the combined list of `LockedChannelList` and (optionally) `SelectedChannelList` via `GraphSelectedChannelsNotification`.
|
||
|
|
* **`void OnFilterChanged(FilterParameterArgs args)`**: Filters `ChannelList` based on the string provided in `args.Param` and updates `FilteredChannelList`.
|
||
|
|
* **`void AddLockedGroupChannels(string testName, string groupName, List<ITestChannel> channels, bool isLocked)`**: Adds or removes a group of channels to/from the `LockedChannelList`. Updates channel colors and locks. Triggers `UpdateChannelLocks`.
|
||
|
|
* **`void AddLockedChannel(ITestChannel channel, bool isLocked)`**: Adds or removes a single channel to/from the `LockedChannelList`. Manages selection state if the channel was previously selected. Triggers `UpdateChannelLocks`.
|
||
|
|
* **`void AddSelectedGroupChannels(string groupName, List<ITestChannel> channels)`**: Replaces the `SelectedChannelList` with the provided channels and assigns colors.
|
||
|
|
* **`void AddSelectedGroup(TestGroup group)`**: Marks a specific `TestGroup` as selected.
|
||
|
|
* **`void AddSelectedChannel(ITestChannel channel, bool reset)`**: Adds a channel to `SelectedChannelList`. If `reset` is true, clears existing selection first. Handles graph channels by selecting their group instead.
|
||
|
|
* **`void AddSelectedChannel(ITestChannel channel)`**: Overload that resets the selection before adding the new channel.
|
||
|
|
* **`void TestChannelsTree_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)`**: Handles collection change events for the tree, wiring up `PropertyChanged` listeners.
|
||
|
|
* **`void GraphList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)`**: Handles collection change events for the channel list, wiring up `PropertyChanged` listeners.
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
* **Maximum Locked Channels**: The system enforces a hard limit of **8** locked channels (`MAX_LOCKED_CHANNELS`). The `UpdateChannelLocks` method disables the ability to lock further channels once this limit is reached.
|
||
|
|
* **Color Assignment**: Channels are assigned colors from a predefined list (`_graphColors`). Transparent is reserved (default). The system attempts to assign unused colors first; if all colors are exhausted, it cycles through them using modulo arithmetic.
|
||
|
|
* **Locked vs. Selected**: A channel cannot be both locked and selected. Locking a channel removes it from `SelectedChannelList`.
|
||
|
|
* **Parent Scoping**: Event handlers (e.g., `OnTestSummaryChanged`) verify that the event's `ParentVM` matches the instance's `Parent` before processing, ensuring multiple instances of the view model do not interfere with each other.
|
||
|
|
* **Locked-Only Mode**: If the `Parent` is of type `IPSDReportMainViewModel`, the `_lockedOnly` flag is set to `true`. In this mode, `PublishSelectedChannels` only publishes locked channels, ignoring selected channels.
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### Internal Dependencies
|
||
|
|
* `DTS.Common.Base`: `BaseViewModel`
|
||
|
|
* `DTS.Common.Enums.Sensors`: `CalibrationBehaviors`, `IsoViewMode`
|
||
|
|
* `DTS.Common.Events`: `TestSummaryChangeNotificationArg`, `GraphClearNotificationArg`, `FilterParameterArgs`, etc.
|
||
|
|
* `DTS.Common.Interactivity`: `InteractionRequest`, `Notification`, `Confirmation`
|
||
|
|
* `DTS.Common.Interface`: `ITestChannel`, `ITestSummary`, `IBaseViewModel`, `IFilterView`, etc.
|
||
|
|
* `DTS.Common.Utils`: `Utils` static helper.
|
||
|
|
* `DTS.Serialization.SliceRaw.File.PersistentChannel`: Used for ISO code retrieval delegate.
|
||
|
|
|
||
|
|
### External Dependencies
|
||
|
|
* `Prism.Events`: `IEventAggregator` (Pub/Sub events).
|
||
|
|
* `Prism.Regions`: `IRegionManager` (Navigation/Region management).
|
||
|
|
* `Unity`: `IUnityContainer` (Dependency Injection).
|
||
|
|
* `System.Windows.Media`: `Color`, `Colors`.
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
* **Explicit GC Collection**: The method `CleanSelection()` explicitly calls `GC.Collect()`. This is generally discouraged in production code and may indicate a historical attempt to force cleanup of unmanaged resources or large objects.
|
||
|
|
* **Lazy Loading Side-Effect**: In `OnTestSummaryChanged`, there is a check `if (l.Channels.FirstOrDefault() == null)`. If the first channel is null, it forces a load operation using `Utils.SetChannelInfo`. This implies that `ITestSummary` objects passed to this VM might be partially initialized stubs.
|
||
|
|
* **Commented Out Event Subscription**: The subscription to `GraphChannelsReadCompletedNotification` is commented out with the note "It does not work", suggesting incomplete functionality or a known bug in the event chain.
|
||
|
|
* **Empty Event Handlers**: Several event handlers (`OnCalibrationBehaviorSettableInViewerChanged`, `TestChannelsTree_PropertyChanged`, `GraphList_PropertyChanged`) contain empty bodies or logic that does nothing (e.g., `if (e.PropertyName != "TestChannelsTree") { }`). This suggests either dead code or placeholders for future logic.
|
||
|
|
* **Calibration Behavior Mutation**: When `CalibrationBehaviors.UseBothIfAvailable` is active, the code modifies the `ChannelDescriptionString` of the channel objects directly by appending "(NonLinear)" or "(Linear)". This mutates the data objects which might be shared elsewhere.
|
||
|
|
* **Color Index Logic**: The logic in `GetNextColor` for handling the case where `channelCount >= _graphColors.Count` contains a redundant check (`if (nextColorIndex >= _graphColors.Count)`), as the modulo math ensures the index is within bounds, though the `+1` offset logic makes it slightly fragile regarding the list size.
|