This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Classes/VirtualToggleButton.cs
generated_at: "2026-04-16T11:10:12.391241+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "001b39a3411ec3ba"
---
# Documentation: VirtualToggleButton.cs
## 1. Purpose
`VirtualToggleButton` is a static utility class that provides attached dependency properties to imbue any WPF element with toggle button behavior without requiring inheritance from `ToggleButton`. It enables elements to respond to mouse clicks and keyboard input (Space/Enter) to toggle between checked/unchecked/indeterminate states, and raises the corresponding routed events. This is useful for templated controls or custom elements that need toggle semantics without the overhead of full `ToggleButton` derivation.
---
## 2. Public Interface
### Attached Properties
| Property | Type | Default | Metadata Flags |
|----------|------|---------|----------------|
| `IsLockedProperty` | `Nullable<bool>` | `false` | `BindsTwoWayByDefault`, `Journal` |
| `IsThreeStateProperty` | `bool` | `false` | None |
| `IsVirtualToggleButtonProperty` | `bool` | `false` | None |
### Public Methods
#### `GetIsLocked(DependencyObject d) -> Nullable<bool>`
Retrieves the current locked/checked state of the target element.
#### `SetIsLocked(DependencyObject d, Nullable<bool> value)`
Sets the locked/checked state. Setting to `true` raises `ToggleButton.CheckedEvent`; `false` raises `ToggleButton.UncheckedEvent`; `null` raises `ToggleButton.IndeterminateEvent`.
#### `GetIsThreeState(DependencyObject d) -> bool`
Returns whether the target supports three-state behavior (true/false/null).
#### `SetIsThreeState(DependencyObject d, bool value)`
Enables or disables three-state mode. When `true`, `IsLocked` can be set to `null` as a third state.
#### `GetIsVirtualToggleButton(DependencyObject d) -> bool`
Returns whether the target is currently acting as a virtual toggle button.
#### `SetIsVirtualToggleButton(DependencyObject d, bool value)`
When set to `true`, attaches `MouseLeftButtonDown` and `KeyDown` handlers to the target (must implement `IInputElement`). When set to `false`, detaches these handlers.
### Internal Methods
#### `RaiseCheckedEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.CheckedEvent` on the target element. Returns `null` if target is null.
#### `RaiseUncheckedEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.UncheckedEvent` on the target element. Returns `null` if target is null.
#### `RaiseIndeterminateEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.IndeterminateEvent` on the target element. Returns `null` if target is null.
---
## 3. Invariants
1. **Two-way binding by default**: `IsLockedProperty` is registered with `BindsTwoWayByDefault`, so bindings will update the source automatically.
2. **Event attachment requirement**: `IsVirtualToggleButton` only attaches event handlers if the target implements `IInputElement`. Non-`IInputElement` targets are silently ignored.
3. **Event raising requirement**: `RaiseEvent()` only works for targets that are either `UIElement` or `ContentElement`. Other `DependencyObject` types will not raise events.
4. **Toggle cycle behavior**:
- When `IsThreeState` is `false`: toggles between `true` and `false` only.
- When `IsThreeState` is `true`: cycles through `false``true``null``false`.
5. **Keyboard handling constraints**:
- Space key is ignored when Alt modifier is present (to avoid interfering with system menu).
- Enter key only triggers toggle if `KeyboardNavigation.AcceptsReturnProperty` is `true` on the sender.
6. **Event source filtering**: `OnKeyDown` only processes events where `e.OriginalSource == sender`, preventing handling of bubbled events from child elements.
---
## 4. Dependencies
### This module depends on:
- `System` (core types)
- `System.Windows` (`DependencyObject`, `DependencyProperty`, `FrameworkPropertyMetadata`, `UIElement`, `ContentElement`, `RoutedEventArgs`, `IInputElement`)
- `System.Windows.Controls.Primitives` (`ToggleButton` - for `CheckedEvent`, `UncheckedEvent`, `IndeterminateEvent`)
- `System.Windows.Input` (`Key`, `KeyEventArgs`, `Keyboard`, `KeyboardNavigation`, `ModifierKeys`, `MouseButtonEventArgs`)
### Consumers:
- Unclear from source alone. Any XAML or code in the `DTS.Viewer.GraphList` namespace or referencing it may use these attached properties.
---
## 5. Gotchas
1. **Misleading XML documentation**: The XML comments for `IsLocked` state "indicates whether the toggle button is checked" — this appears to be copy-pasted from a standard `ToggleButton` implementation. The property is named `IsLocked`, not `IsChecked`, which may indicate domain-specific semantics (e.g., locking a graph item vs. selecting it).
2. **Type mismatch between event raising methods**: `RaiseCheckedEvent`, `RaiseUncheckedEvent`, and `RaiseIndeterminateEvent` accept only `UIElement`, but the private `RaiseEvent` helper supports both `UIElement` and `ContentElement`. If a `ContentElement` has `IsLocked` set, the change handler will attempt to raise events on it via `RaiseEvent`, but the public `RaiseXxxEvent` methods cannot be called with `ContentElement` directly.
3. **Null return from event methods**: The `RaiseXxxEvent` methods return `null` when the target is null, but they do not throw. Callers should check for null if they intend to use the returned `RoutedEventArgs`.
4. **Local variable shadows property name**: In `UpdateIsLocked()`, the local variable is named `IsLocked`, which shadows the property accessor method naming convention. This is legal but could cause confusion during debugging.
5. **No validation of IsThreeState consistency**: Setting `IsLocked` to `null` is always possible regardless of `IsThreeState` value. The `IsThreeState` property only affects toggle behavior in `UpdateIsLocked()`, not direct programmatic assignment.

View File

@@ -0,0 +1,117 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Model/GraphPropertyObject.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Model/GraphObject.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Model/TreeViewChannels.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Model/TreeViewIds.cs
generated_at: "2026-04-16T11:11:47.054703+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "47d9a78e7853eabc"
---
# Documentation: DTS.Viewer.GraphList.Models
## 1. Purpose
This module provides the data model classes for the Graph List functionality within the DTS Viewer application. It defines the structure for individual graph objects (`GraphObject`, `GraphPropertyObject`) and the hierarchical view models required to populate WPF TreeView controls (`TreeViewChannels`, `TreeViewIds`). The module bridges raw data with UI-specific behaviors, implementing `INotifyPropertyChanged` for data binding and handling complex selection logic for channel and event navigation.
## 2. Public Interface
### Class: `GraphPropertyObject`
Located in `DTS.Viewer.GraphList.Model`. A POCO-style class decorated with attributes for the Xceed WPF Toolkit PropertyGrid.
* **`GraphPropertyObject()`**: Default constructor.
* **`int Id`**: Read-only property categorized under "Information".
* **`string Name`**: Read-only property categorized under "Information".
* **`string Description`**: Read-only property categorized under "Information".
* **`string Filter`**: Categorized under "Parameters"; uses `ItemsSource(typeof(CFCFilterItemSource))`.
* **`string DataFlag`**: Categorized under "Parameters".
* **`double ShiftT0`**: Categorized under "Parameters".
* **`double EuMultiplier`**: Categorized under "Parameters".
* **`double EuOffset`**: Categorized under "Parameters".
### Class: `GraphObject`
Located in `DTS.Viewer.GraphList.Model`. Implements `IBaseClass`. Represents a single graph entity containing both data and display parameters.
* **`GraphObject()`**: Constructor that calls `LoadGraphs()`.
* **`int RecordId`**: Gets or sets the record ID; notifies property change.
* **`int Id`**: Gets or sets the ID; synchronizes with `Property.Id`.
* **`string Name`**: Gets or sets the name; synchronizes with `Property.Name`.
* **`string Description`**: Gets or sets the description; synchronizes with `Property.Description`.
* **`CFCFilter Filter`**: Gets or sets the filter; synchronizes with `Property.Filter` (converted to string).
* **`string DataFlag`**: Gets or sets the data flag; synchronizes with `Property.DataFlag`.
* **`double ShiftT0`**: Gets or sets the T0 shift; synchronizes with `Property.ShiftT0`.
* **`double EuMultiplier`**: Gets or sets the EU multiplier; synchronizes with `Property.EuMultiplier`.
* **`double EuOffset`**: Gets or sets the EU offset; synchronizes with `Property.EuOffset`.
* **`List<double> Data`**: Gets or sets the list of data points.
* **`bool Visable`**: Gets or sets the visibility state.
* **`GraphPropertyObject Property`**: Gets or sets the internal property object wrapper.
* **`event PropertyChangedEventHandler PropertyChanged`**: Event for property change notification.
* **`void OnPropertyChanged(string propertyName)`**: Invokes the `PropertyChanged` event.
### Class: `TreeViewChannels`
Located in `DTS.Viewer.GraphList`. Implements `IBaseModel`. Root node for binding a channel-based TreeView.
* **`string Name`**: Gets or sets the node name.
* **`ObservableCollection<TestGroup> Groups`**: Gets or sets the child groups; updates `GroupsCount` on set.
* **`int GroupsCount`**: Gets or sets the count of groups.
* **`string Path`**: Gets or sets the path.
* **`bool IsSaved`**: Getter only (read-only).
* **`bool IsExpanded`**: Gets or sets the expanded state of the TreeView node.
* **`bool IsSelected`**: Gets or sets the selected state.
### Class: `TestGroup`
Located in `DTS.Viewer.GraphList`. Child node for `TreeViewChannels`.
* **`IBaseViewModel Parent`**: Gets or sets the parent ViewModel.
* **`bool IsLocked`**: Gets or sets the locked state; calls `((IGraphMainViewModel)Parent).AddLockedGroupChannels(...)` on set.
* **`bool IsSelected`**: Gets or sets the selected state; calls `((IGraphMainViewModel)Parent).AddSelectedGroupChannels(...)` on set. Ignores selection if `Name` starts with "Test Channels" or "Calculated Channels".
* **`bool CanLock`**: Controls whether the item can be locked.
* **`ObservableCollection<ITestChannel> Channels`**: Gets or sets the collection of channels.
* **Other Properties**: `Path`, `DTSFile`, `IsGraph`, `IsExpanded`, `TestName`, `Name`, `DisplayName`, `ChannelCount`.
### Class: `TreeViewIds`
Located in `DTS.Viewer.GraphList`. Implements `IBaseModel`. Root node for binding an ID/Event-based TreeView.
* **`IBaseViewModel Parent`**: Gets or sets the parent ViewModel.
* **`int TreeIndex`**: Gets or sets the index of this tree node.
* **`ObservableCollection<ITestEvent> Events`**: Gets or sets child events.
* **`bool IsSelected`**: Gets or sets the selected state; manages cascading selection to children via `SetChildNodes`.
* **`void SetChildNodes(bool isSelected)`**: Iterates through `Events` and sets their `IsSelected` property.
* **`static void SetIsItemSelected(UIElement element, bool value)`**: Attached property setter for `IsItemSelectedProperty`.
### Class: `TestEvent`
Located in `DTS.Viewer.GraphList`. Implements `ITestEvent`. Child node for `TreeViewIds`.
* **`bool IsSelected`**: Complex setter that handles Shift/Ctrl key logic for multi-selection. Interacts with `IExportGraphMainViewModel` to manage selection lists (`AddToSelectedEvents`, `RemoveFromSelectedEvents`).
* **`bool IsLocked`**: Gets or sets locked state; calls `((IExportGraphMainViewModel)parent).AddLockedEvents(...)` on set.
* **Other Properties**: `Path`, `Parent`, `IsGraph`, `IsExpanded`, `CanLock`, `TestName`, `Name`, `TestSetupName`, `TestItem`, `DTSFile`, `DataType`, `Events`, `TestId`, `TreeIndex`.
## 3. Invariants
* **Synchronization**: When `GraphObject.Id`, `Name`, `Description`, `Filter`, `DataFlag`, `ShiftT0`, `EuMultiplier`, or `EuOffset` are set, the corresponding property on the internal `GraphPropertyObject` instance (accessed via `Property`) must be updated immediately.
* **Type Conversion**: `GraphObject.Filter` is of type `CFCFilter` (enum), but it is stored as a `string` in `GraphPropertyObject.Filter`.
* **Collection Counts**: Setting `TreeViewChannels.Groups` automatically updates `GroupsCount`. Setting `TestGroup.Channels` automatically updates `ChannelCount`. Setting `TreeViewIds.Events` automatically updates `EventCount`.
* **Parent Interface Requirements**:
* `TestGroup` requires its `Parent` to be castable to `IGraphMainViewModel`.
* `TreeViewIds` and `TestEvent` require their `Parent` to be castable to `IExportGraphMainViewModel`.
## 4. Dependencies
**Internal Dependencies (Inferred from imports):**
* `DTS.Common`: Uses `CFCFilter` enum and `CFCFilterItemSource`.
* `DTS.Common.Base`: Uses `IBaseClass`, `IBaseModel`.
* `DTS.Common.Interface`: Uses `IBaseViewModel`, `ITestChannel`, `ITestEvent`, `IGraphMainViewModel`, `IExportGraphMainViewModel`.
**External Dependencies:**
* `Xceed.Wpf.Toolkit.PropertyGrid.Attributes`: Used for `Category`, `DisplayName`, `ReadOnly`, `Description`, and `ItemsSource` attributes in `GraphPropertyObject`.
* `System.Windows`: Used for `DependencyProperty`, `UIElement`, `Input.Keyboard`, `Controls.ItemsControl`.
## 5. Gotchas
* **Typo in Property Name**: `GraphObject.Visable` appears to be a typo for "Visible".
* **Silent Failures in Selection Logic**: In `TreeViewIds.IsSelected`, if `Parent` is null or not of type `IExportGraphMainViewModel`, the setter returns early without setting the backing field or notifying property change.
* **Complex Setter Logic (Side Effects)**:
* Setting `TestGroup.IsSelected` or `TestEvent.IsSelected` triggers logic in the parent ViewModel that modifies global state (selection lists).
* `TestEvent.IsSelected` reads static keyboard state (`Keyboard.IsKeyDown`) directly within the property setter. This ties the model tightly to the UI input state and can cause unpredictable behavior if the property is set programmatically rather than via user interaction.
* **Hardcoded String Comparisons

View File

@@ -0,0 +1,50 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T11:10:44.942572+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "af860c5bc7afa07c"
---
# Documentation: DTS.Viewer.GraphList Assembly Metadata
## 1. Purpose
This file provides assembly-level metadata configuration for the `DTS.Viewer.GraphList` module (compiled as `Graph.dll`). It defines version information, copyright details, and COM visibility settings using .NET attributes. This module exists to embed standard manifest information into the compiled assembly, ensuring proper identification and interaction within the larger DTS Viewer application ecosystem.
## 2. Public Interface
This file does not contain public classes, methods, or functions. It strictly applies assembly-level attributes.
**Defined Attributes:**
* **`AssemblyTitle`**: Set to `"Graph"`.
* **`AssemblyDescription`**: Set to an empty string.
* **`AssemblyConfiguration`**: Set to an empty string.
* **`AssemblyCompany`**: Set to an empty string.
* **`AssemblyProduct`**: Set to `"Graph"`.
* **`AssemblyCopyright`**: Set to `"Copyright © 2017"`.
* **`AssemblyTrademark`**: Set to an empty string.
* **`AssemblyCulture`**: Set to an empty string (indicates a culture-neutral assembly).
* **`ComVisible`**: Set to `false`. Prevents types within this assembly from being visible to COM components.
* **`Guid`**: Set to `"61261c58-c32e-4dea-a87a-d7f956f28b4d"`. serves as the ID for the type library if exposed to COM.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
## 3. Invariants
* **Versioning:** The assembly version and file version are explicitly synchronized at `1.0.0.0`.
* **COM Visibility:** Types in this assembly are explicitly hidden from COM components by default (`ComVisible(false)`).
* **Culture:** The assembly is strictly culture-neutral (`AssemblyCulture("")`).
## 4. Dependencies
**Internal Dependencies (Imports):**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
**External Dependencies:**
* None identified from source alone. This file relies solely on standard .NET Framework libraries.
## 5. Gotchas
* **Naming Inconsistency:** The `AssemblyTitle` and `AssemblyProduct` attributes are set to `"Graph"`, whereas the project directory implies the module name is `DTS.Viewer.GraphList`. This discrepancy suggests the metadata may not have been updated to match the project namespace, or the module is colloquially referred to as "Graph" internally.
* **Sparse Metadata:** The `AssemblyDescription`, `AssemblyCompany`, and `AssemblyConfiguration` fields are empty strings, which may result in sparse metadata visibility in file properties or deployment logs.
* **Hardcoded Version:** The version is hardcoded to `1.0.0.0`. If the build system relies on auto-incrementing versions (e.g., via MSBuild or CI/CD pipelines), this file may need to be auto-generated or ignored during the build process to reflect accurate build numbers.

View File

@@ -0,0 +1,71 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/View/ExportGraphMainView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/View/GraphMainView.xaml.cs
generated_at: "2026-04-16T11:11:08.452052+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "e0305153f9f5be9f"
---
# Documentation: DTS.Viewer.GraphList Views
## 1. Purpose
This module contains WPF code-behind files for two graph-related views in the DTS Viewer application: `ExportGraphMainView` and `GraphMainView`. Both views implement corresponding interfaces from `DTS.Common.Interface` and provide interaction logic for their respective XAML counterparts. Their primary runtime behavior is to intercept and suppress the `ApplicationCommands.Undo` command, preventing undo operations from propagating further in the command routing system.
---
## 2. Public Interface
### `ExportGraphMainView` (class)
**Implements:** `IExportGraphMainView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public ExportGraphMainView()` | Initializes the XAML component via `InitializeComponent()` and registers a `CommandBinding` for `ApplicationCommands.Undo`. Both the Execute and CanExecute handlers set `e.Handled = true` without performing any other action. |
---
### `GraphMainView` (class)
**Implements:** `IGraphMainView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public GraphMainView()` | Initializes the XAML component via `InitializeComponent()` and registers a `CommandBinding` for `ApplicationCommands.Undo`. Both the Execute and CanExecute handlers set `e.Handled = true` without performing any other action. |
**Note:** The `GraphMainView` class contains commented-out code referencing:
- `root.IsChecked` (presumably a UI element)
- `TvTestChannels.Focus()` (a method call)
- A commented-out method `SetTvFocus()`
---
## 3. Invariants
1. **Partial Class Structure:** Both `ExportGraphMainView` and `GraphMainView` are declared as `partial` classes, implying the existence of XAML-generated counterparts that must be present at compile time.
2. **Undo Command Suppression:** Both views guarantee that `ApplicationCommands.Undo` will always be marked as handled (`e.Handled = true`) in both Execute and CanExecute handlers, effectively disabling undo functionality within these views.
3. **Interface Implementation:** Each view must implement its respective interface (`IExportGraphMainView` or `IGraphMainView`) from `DTS.Common.Interface`.
---
## 4. Dependencies
### This module depends on:
- `System.Windows.Input` — Provides `CommandBinding` and `ApplicationCommands`
- `DTS.Common.Interface` — Provides `IExportGraphMainView` and `IGraphMainView` interfaces
### What depends on this module:
- **Not determinable from source alone.** The views are likely instantiated by a view factory, dependency injection container, or referenced by view models in the `DTS.Viewer.GraphList` module or a higher-level orchestration layer.
---
## 5. Gotchas
1. **No-op Undo Handlers:** Both views register command bindings for `ApplicationCommands.Undo` that do nothing except mark the event as handled. This effectively disables undo functionality without providing alternative behavior. The intent is unclear from source alone—this may be intentional suppression or placeholder code.
2. **Commented-Out Code in `GraphMainView`:** The presence of commented-out references to `root.IsChecked`, `TvTestChannels.Focus()`, and the `SetTvFocus()` method suggests incomplete or removed functionality. The original purpose of these members cannot be determined from source alone.
3. **Namespace Suppression:** Both files include `// ReSharper disable CheckNamespace`, indicating the namespace `DTS.Viewer.GraphList` may not match the folder structure (`DTS.Viewer.Modules/DTS.Viewer.GraphList/View/`). This could cause confusion when navigating the codebase.

View File

@@ -0,0 +1,93 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/ViewModel/GraphMainViewModel.cs
generated_at: "2026-04-16T11:10:28.732851+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "09077834bf97663d"
---
# Documentation: GraphMainViewModel.cs
## 1. Purpose
The `GraphMainViewModel` class acts as the presentation logic controller for the Graph List module within the DTS Viewer application. It is responsible for managing the lifecycle of test channels—retrieving them from test summaries, organizing them into a hierarchical tree structure (Test > Group > Channel), and handling user interactions for selecting or locking channels for visualization. It serves as a bridge between the data layer (test summaries, metadata) and the UI layer, publishing events to notify other parts of the system when channels are selected, locked, or cleared.
## 2. Public Interface
### Public Properties
* **`IFilterView FilterView`**: Gets the filter view instance associated with this ViewModel.
* **`IGraphMainView View`**: Gets or sets the associated view interface.
* **`IBaseViewModel Parent`**: Gets or sets the parent ViewModel (used to scope events and behavior).
* **`InteractionRequest<Notification> NotificationRequest`**: Used to raise notification dialogs.
* **`InteractionRequest<Confirmation> ConfirmationRequest`**: Used to raise confirmation dialogs (hides base member).
* **`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<ITestChannel> ChannelList`**: The master list of all available channels.
* **`ObservableCollection<ITestChannel> FilteredChannelList`**: The list of channels displayed to the user after filtering is applied.
* **`ObservableCollection<TreeViewChannels> TestChannelsTree`**: The hierarchical structure of channels bound to the UI TreeView.
* **`bool IsFilterEnabled`**: Indicates if the filter UI should be enabled (true if `ChannelList` has items).
* **`string SelectedGroupName`**: The name of the currently selected group.
* **`string LockedGroupName`**: The name of the currently locked group.
* **`bool TestModified`**: Indicates if the underlying test data has been modified.
### Public Methods
* **`void Initialize()`**: Overrides base method; currently empty.
* **`void Initialize(object parameter)`**: Initializes the ViewModel, sets the `Parent`, determines if locked-only mode is active (if Parent is `IPSDReportMainViewModel`), initializes the filter view, and subscribes to events.
* **`void PublishSelectedChannels()`**: Publishes the `GraphSelectedChannelsNotification` and `GraphSelectedChannelCountNotification` events containing the current lists of locked and/or selected channels.
* **`void AddLockedGroupChannels(string testName, string groupName, List<ITestChannel> channels, bool isLocked)`**: Adds or removes a group of channels to/from the `LockedChannelList`.
* **`void AddLockedChannel(ITestChannel channel, bool isLocked)`**: Adds or removes a single channel to/from the `LockedChannelList`.
* **`void AddSelectedGroupChannels(string groupName, List<ITestChannel> channels)`**: Selects a specific group of channels, resetting previous selections.
* **`void AddSelectedGroup(TestGroup group)`**: Marks a specific `TestGroup` as selected.
* **`void AddSelectedChannel(ITestChannel channel, bool reset)`**: Adds a single channel to the `SelectedChannelList`. If `reset` is true, previous selections are cleared.
* **`void AddSelectedChannel(ITestChannel channel)`**: Overload that resets previous selections before adding the new channel.
* **`void OnFilterChanged(FilterParameterArgs args)`**: Filters the `ChannelList` based on a string parameter and updates `FilteredChannelList`.
* **`void Activated()`**: Overrides base method; publishes an empty `FilterParameterChangedEvent` to reset the filter.
## 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.
* **Mutual Exclusivity**: A channel cannot be simultaneously in the `SelectedChannelList` and `LockedChannelList`. Locking a channel removes it from the selected list.
* **Color Assignment**: Channels are assigned colors from a fixed palette (`_graphColors`). The `GetNextColor` method ensures colors are unique if available, or cycles through the palette if the channel count exceeds the color count.
* **Parent Scoping**: Event handlers (e.g., `OnTestSummaryChanged`) check if the event's `ParentVM` matches the ViewModel's `Parent` property to ensure the event is relevant to this specific instance.
* **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
### External Dependencies
* **Prism**: `IEventAggregator`, `IRegionManager` (for event pub/sub and region navigation).
* **Unity**: `IUnityContainer` (for dependency resolution).
* **System.Windows.Media**: `Color`, `Colors` (for channel visualization).
### Internal Dependencies (Inferred)
* **DTS.Common.Interface**: `ITestChannel`, `ITestSummary`, `IGraphMainView`, `IFilterView`, `ITestModificationModel`.
* **DTS.Common.Events**: `TestSummaryChangeNotificationArg`, `GraphClearNotificationArg`, `FilterParameterArgs`, etc.
* **DTS.Common.Enums.Sensors**: `CalibrationBehaviors`, `IsoViewMode`.
* **DTS.Serialization**: Referenced via `Utils.SetChannelInfo` for lazy loading channel metadata.
### Events Consumed
* `RaiseNotification`
* `FilterParameterChangedEvent`
* `TestSummaryChangeNotification`
* `TestModificationChangedEvent`
* `CalibrationBehaviorSettingChangedEvent`
* `CalibrationBehaviorSettableInViewerChangedEvent`
* `ChannelCodesViewChangedEvent`
### Events Published
* `GraphClearNotification`
* `GraphLoadedCountNotification`
* `GraphSelectedChannelCountNotification`
* `GraphSelectedChannelsNotification`
* `BusyIndicatorChangeNotification`
* `FilterParameterChangedEvent`
## 5. Gotchas
* **Member Hiding**: The class uses the `new` keyword to hide base members (`ConfirmationRequest`, `PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`). Accessing these via a base class reference will bypass the logic defined in `GraphMainViewModel`.
* **Explicit GC Collection**: The `CleanSelection` method explicitly calls `GC.Collect()`. This is generally discouraged in .NET development and could introduce performance pauses.
* **Lazy Loading Side Effect**: Inside `OnTestSummaryChanged`, there is a check `if (l.Channels.FirstOrDefault() == null)`. If true, it triggers `Utils.SetChannelInfo`, which modifies `l.Channels`, `l.Graphs`, and `l.CalculatedChannels` in place. This suggests the data object passed via the event is mutable and potentially incomplete prior to this handler executing.
* **Calibration Logic Mutation**: The `OnTestSummaryChanged` method modifies the `tsChannels` list (removing items or modifying `ChannelDescriptionString`) based on `calibrationBehaviorSetting`. This alters the data before it is displayed, specifically handling Linear vs. NonLinear calibration duplicates.
* **Dead Code / Empty Handlers**:
* The subscription to `GraphChannelsReadCompletedNotification` is commented out with the note "It does not work".
* Event handlers `TestChannelsTree_PropertyChanged` and `GraphList_PropertyChanged` contain empty `if` blocks (e.g., `if (e.PropertyName != "TestChannelsTree") { }`), which appears to be incomplete logic.
* `OnCalibrationBehaviorSettableInViewerChanged` is subscribed but has an empty implementation body.