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,102 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Classes/VirtualToggleButton.cs
generated_at: "2026-04-16T13:48:16.790928+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "001b39a3411ec3ba"
---
# Documentation: VirtualToggleButton
## 1. Purpose
`VirtualToggleButton` is a static helper class that provides attached dependency properties to imbue any WPF element with toggle button behavior. Rather than requiring inheritance from `ToggleButton`, this module allows arbitrary `DependencyObject` instances (specifically those implementing `IInputElement`) to respond to mouse clicks and keyboard input (Space/Enter) by toggling between checked, unchecked, and optionally indeterminate states. This is used within the `DTS.Viewer.GraphList` module to create toggle-style interactions on elements that cannot directly inherit from `ToggleButton`.
---
## 2. Public Interface
### Attached Properties
#### `IsLockedProperty`
- **Type:** `DependencyProperty` (attached)
- **Value Type:** `Nullable<bool>`
- **Default Value:** `false`
- **Metadata Flags:** `BindsTwoWayByDefault | Journal`
- **Get Accessor:** `Nullable<bool> GetIsLocked(DependencyObject d)`
- **Set Accessor:** `void SetIsLocked(DependencyObject d, Nullable<bool> value)`
- **Behavior:** Represents the toggle state. When changed, raises `ToggleButton.CheckedEvent` (if `true`), `ToggleButton.UncheckedEvent` (if `false`), or `ToggleButton.IndeterminateEvent` (if `null`).
#### `IsThreeStateProperty`
- **Type:** `DependencyProperty` (attached)
- **Value Type:** `bool`
- **Default Value:** `false`
- **Get Accessor:** `bool GetIsThreeState(DependencyObject d)`
- **Set Accessor:** `void SetIsThreeState(DependencyObject d, bool value)`
- **Behavior:** When `true`, allows `IsLocked` to cycle through `null` (indeterminate) state during toggle operations.
#### `IsVirtualToggleButtonProperty`
- **Type:** `DependencyProperty` (attached)
- **Value Type:** `bool`
- **Default Value:** `false`
- **Get Accessor:** `bool GetIsVirtualToggleButton(DependencyObject d)`
- **Set Accessor:** `void SetIsVirtualToggleButton(DependencyObject d, bool value)`
- **Behavior:** When set to `true` on an `IInputElement`, subscribes `OnMouseLeftButtonDown` and `OnKeyDown` handlers. When set to `false`, unsubscribes them.
### Internal Methods
#### `RaiseCheckedEvent(UIElement target)`
- **Returns:** `RoutedEventArgs` or `null` if target is null
- **Behavior:** Raises `ToggleButton.CheckedEvent` on the target element.
#### `RaiseUncheckedEvent(UIElement target)`
- **Returns:** `RoutedEventArgs` or `null` if target is null
- **Behavior:** Raises `ToggleButton.UncheckedEvent` on the target element.
#### `RaiseIndeterminateEvent(UIElement target)`
- **Returns:** `RoutedEventArgs` or `null` if target is null
- **Behavior:** Raises `ToggleButton.IndeterminateEvent` on the target element.
---
## 3. Invariants
1. **Input Handler Attachment:** Setting `IsVirtualToggleButton` to `true` on a non-`IInputElement` has no effect (handlers are not attached, no exception is thrown).
2. **Toggle State Cycling Logic (in `UpdateIsLocked`):**
- If `IsLocked == true`: Sets to `false`, or `null` if `IsThreeState` is `true`.
- If `IsLocked == false` or `null`: Sets to `true`.
3. **Keyboard Handling:**
- `Space` key toggles the state, unless `Alt` modifier is present (system menu invocation is preserved).
- `Enter` key toggles the state only if `KeyboardNavigation.AcceptsReturnProperty` is `true` on the sender.
4. **Event Routing:** Raised events use `ToggleButton.CheckedEvent`, `ToggleButton.UncheckedEvent`, and `ToggleButton.IndeterminateEvent` as routed event identifiers.
---
## 4. Dependencies
### This Module Depends On:
- `System`
- `System.Windows` (`DependencyObject`, `DependencyProperty`, `FrameworkPropertyMetadata`, `UIElement`, `ContentElement`, `RoutedEventArgs`, `IInputElement`)
- `System.Windows.Controls.Primitives` (`ToggleButton`)
- `System.Windows.Input` (`Key`, `KeyEventArgs`, `Keyboard`, `KeyboardNavigation`, `ModifierKeys`, `MouseButtonEventArgs`)
### Consumers:
- Unclear from source alone. The class is in `DTS.Viewer.GraphList` namespace, suggesting consumption by GraphList-related components.
---
## 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 `IsChecked` property. The property name `IsLocked` suggests a different semantic meaning (possibly "locked/selected" in the context of graph items).
2. **Type Inconsistency in Event Raising:** The private `RaiseEvent` method supports both `UIElement` and `ContentElement`, but the internal `RaiseCheckedEvent`, `RaiseUncheckedEvent`, and `RaiseIndeterminateEvent` methods only accept `UIElement`. If a `ContentElement` needs these events raised, the internal methods cannot be used directly.
3. **Namespace Suppression:** The file contains `// ReSharper disable CheckNamespace`, indicating the namespace `DTS.Viewer.GraphList` may not match the project's default namespace structure. This could indicate a refactoring artifact or intentional namespace override.
4. **No Null Guard in `UpdateIsLocked`:** The method casts `sender as DependencyObject` without null-checking before calling `GetIsLocked(d)`. If called with a non-`DependencyObject` sender, this would pass null to `GetIsLocked`, which would throw a `NullReferenceException` inside `d.GetValue()`.
5. **Event Handled Flag:** Both `OnMouseLeftButtonDown` and `OnKeyDown` mark events as `e.Handled = true`, which may prevent bubbling to parent handlers unexpectedly.

View File

@@ -0,0 +1,253 @@
---
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-16T13:49:42.163558+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "47d9a78e7853eabc"
---
# Documentation: DTS.Viewer.GraphList.Model
## 1. Purpose
This module provides the data model classes for the Graph List feature in the DTS Viewer application. It defines hierarchical tree structures for displaying test channels and events in WPF TreeView controls, along with graph property objects that integrate with the Xceed WPF Toolkit PropertyGrid. The module serves as the presentation model layer, bridging raw test data to UI components while supporting features like multi-selection with keyboard modifiers, locking, and property editing.
---
## 2. Public Interface
### GraphPropertyObject
A model class designed for display in a WPF PropertyGrid control.
**Constructor:**
- `GraphPropertyObject()` - Default parameterless constructor.
**Properties:**
| Property | Type | Category | Access | Description |
|----------|------|----------|--------|-------------|
| `Id` | `int` | Information | Read-only | Unique identifier for the graph. |
| `Name` | `string` | Information | Read-only | Name of the graph. |
| `Description` | `string` | Information | Read-only | Description text. |
| `Filter` | `string` | Parameters | Read/Write | Filter value; uses `CFCFilterItemSource` for item selection. |
| `DataFlag` | `string` | Parameters | Read/Write | Data flag string. |
| `ShiftT0` | `double` | Parameters | Read/Write | Time shift in milliseconds. |
| `EuMultiplier` | `double` | Parameters | Read/Write | Engineering unit multiplier. |
| `EuOffset` | `double` | Parameters | Read/Write | Engineering unit offset. |
---
### GraphObject : IBaseClass
A model class representing a graph with its data and parameters. Implements `INotifyPropertyChanged` pattern.
**Constructor:**
- `GraphObject()` - Initializes the object and calls `LoadGraphs()`.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `RecordId` | `int` | Record identifier with change notification. |
| `Id` | `int` | Graph ID; setter also updates `Property.Id`. |
| `Name` | `string` | Graph name; setter also updates `Property.Name`. |
| `Description` | `string` | Description; setter also updates `Property.Description`. |
| `Filter` | `CFCFilter` | Filter enum value; setter converts to string and updates `Property.Filter`. |
| `DataFlag` | `string` | Data flag; setter also updates `Property.DataFlag`. |
| `ShiftT0` | `double` | Time shift; setter also updates `Property.ShiftT0`. |
| `EuMultiplier` | `double` | EU multiplier; setter also updates `Property.EuMultiplier`. |
| `EuOffset` | `double` | EU offset; setter also updates `Property.EuOffset`. |
| `Data` | `List<double>` | List of data points. |
| `Visable` | `bool` | Visibility flag (note: typo in original). |
| `Property` | `GraphPropertyObject` | Nested property object for PropertyGrid binding. |
**Events:**
- `PropertyChanged` - `PropertyChangedEventHandler` event for property change notifications.
**Methods:**
- `void OnPropertyChanged(string propertyName)` - Raises the `PropertyChanged` event.
- `void LoadGraphs()` - Private method; currently contains commented-out service controller code.
---
### TreeViewChannels : IBaseModel
Root node model for binding to a TreeView displaying test groups.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `Name` | `string` | Node name. |
| `Groups` | `ObservableCollection<TestGroup>` | Collection of child test groups; setter updates `GroupsCount`. |
| `GroupsCount` | `int` | Count of groups. |
| `Path` | `string` | File path. |
| `IsSaved` | `bool` | Get-only property (always returns default). |
| `IsExpanded` | `bool` | TreeView expansion state; defaults to `true`. |
| `IsSelected` | `bool` | TreeView selection state; defaults to `false`. |
**Events:**
- `PropertyChanged` - `PropertyChangedEventHandler` event.
**Methods:**
- `void OnPropertyChanged(string propertyName)` - Raises the `PropertyChanged` event.
---
### TestGroup : INotifyPropertyChanged
Child node model representing a test group within the channel tree.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `Path` | `string` | File path. |
| `DTSFile` | `string` | DTS file name. |
| `Parent` | `IBaseViewModel` | Reference to parent ViewModel. |
| `IsLocked` | `bool` | Lock state; setter calls `Parent.AddLockedGroupChannels()`. |
| `IsGraph` | `bool` | Graph flag. |
| `IsExpanded` | `bool` | Expansion state; defaults to `true`. |
| `CanLock` | `bool` | Controls whether item can be locked/selected; defaults to `true`. |
| `IsSelected` | `bool` | Selection state; setter calls `Parent.AddSelectedGroupChannels()` when selected. |
| `TestName` | `string` | Name of the test. |
| `Name` | `string` | Group name. |
| `DisplayName` | `string` | Display name. |
| `Channels` | `ObservableCollection<ITestChannel>` | Collection of channels; setter updates `ChannelCount`. |
| `ChannelCount` | `int` | Count of channels. |
**Events:**
- `PropertyChanged` - `PropertyChangedEventHandler` event.
**Methods:**
- `void OnPropertyChanged(string propertyName)` - Protected virtual method raising `PropertyChanged`.
---
### TreeViewIds : IBaseModel
Root node model for binding to a TreeView displaying test events by ID.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `Parent` | `IBaseViewModel` | Reference to parent ViewModel. |
| `Name` | `string` | Node name. |
| `TreeIndex` | `int` | Index in tree; defaults to `0`. |
| `EventCount` | `int` | Count of events. |
| `Events` | `ObservableCollection<ITestEvent>` | Collection of child events; setter updates `EventCount`. |
| `Path` | `string` | File path. |
| `IsSaved` | `bool` | Get-only property. |
| `IsExpanded` | `bool` | Expansion state; defaults to `true`. |
| `IsSelected` | `bool` | Selection state with cascading child selection logic. |
**Methods:**
- `void OnPropertyChanged(string propertyName)` - Raises the `PropertyChanged` event.
- `void SetChildNodes(bool isSelected)` - Sets `IsSelected` on all child `Events`.
- `static void SetIsItemSelected(UIElement element, bool value)` - Attached property setter.
**Attached Properties:**
- `IsItemSelectedProperty` - `DependencyProperty` registered for `bool` type.
**Static Properties:**
- `IsShiftPressed` - Private static property checking `Key.LeftShift` or `Key.RightShift`.
---
### TestEvent : ITestEvent
Child node model representing a test event with complex multi-selection support.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `Path` | `string` | File path. |
| `Parent` | `IBaseViewModel` | Reference to parent ViewModel. |
| `IsLocked` | `bool` | Lock state; setter calls `Parent.AddLockedEvents()` if parent implements `IExportGraphMainViewModel`. |
| `IsGraph` | `bool` | Graph flag. |
| `IsExpanded` | `bool` | Expansion state; defaults to `true`. |
| `CanLock` | `bool` | Controls whether item can be locked; defaults to `true`. |
| `IsSelected` | `bool` | Selection state with shift/ctrl key handling. |
| `TestName` | `string` | Test name. |
| `Name` | `string` | Event name. |
| `TestSetupName` | `string` | Test setup name. |
| `TestItem` | `string` | Test item identifier. |
| `DTSFile` | `string` | DTS file name. |
| `DataType` | `string` | Data type string. |
| `Events` | `ObservableCollection<ITestEvent>` | Nested events collection. |
| `TestId` | `string` | Test identifier. |
| `TreeIndex` | `int` | Index in tree. |
**Events:**
- `PropertyChanged` - `PropertyChangedEventHandler` event.
**Methods:**
- `void OnPropertyChanged(string propertyName)` - Protected virtual method raising `PropertyChanged`.
**Private Methods (selection logic):**
- `void SetIsSelected(bool value)` - Main selection setter with keyboard modifier handling.
- `void SetIsSelectedShiftPressed(bool value)` - Handles shift-key selection range logic.
- `bool ShouldExitSetIsSelected(bool value)` - Determines if selection should be skipped.
- `void SetIsSelectedShiftNotPressed(bool value)` - Handles non-shift selection logic.
**Static Properties:**
- `IsShiftPressed` - Checks `Key.LeftShift` or `Key.RightShift`.
- `IsCtrlPressed` - Checks `Key.LeftCtrl` or `Key.RightCtrl`.
---
## 3. Invariants
1. **GraphObject-Property Synchronization**: Setting any parameter property (`Id`, `Name`, `Description`, `Filter`, `DataFlag`, `ShiftT0`, `EuMultiplier`, `EuOffset`) on `GraphObject` must also update the corresponding property on the nested `GraphPropertyObject` instance.
2. **Collection-Count Synchronization**:
- `TreeViewChannels.Groups` setter must update `GroupsCount`.
- `TestGroup.Channels` setter must update `ChannelCount`.
- `TreeViewIds.Events` setter must update `EventCount`.
- `TestEvent.Events` setter must update the private `_eventCount`.
3. **Parent Reference Requirement**: `TestGroup` and `TestEvent` require a valid `Parent` reference that implements specific interfaces (`IGraphMainViewModel` or `IExportGraphMainViewModel`) for selection/locking operations to function correctly.
4. **Selection State Flags**: The selection logic in `TreeViewIds` and `TestEvent` relies on coordinated state flags on the parent ViewModel (`SettingChildNodesToTrue`, `SettingOrResettingChildNodes`, `SettingPeerNodeToTrue`, `ResettingAllItems`, `SettingItemsBetween`) to prevent recursive updates.
5. **GraphPropertyObject Initialization**: `GraphObject.Property` is always initialized to a new `GraphPropertyObject` instance in the field initializer.
---
## 4. Dependencies
### This module depends on:
- **DTS.Common** - Provides `CFCFilter` enum and `CFCFilterItemSource` class.
- **DTS.Common.Base** - Provides `IBaseClass` and `IBaseModel` interfaces.
- **DTS.Common.Interface** - Provides `IBaseViewModel`, `IGraphMainViewModel`, `IExportGraphMainViewModel`, `ITestChannel`, and `ITestEvent` interfaces.
- **Xceed.Wpf.Toolkit.PropertyGrid.Attributes** - Provides `Category`, `DisplayName`, `ReadOnly`, `Description`, and `ItemsSource` attributes for PropertyGrid integration.
- **System.Windows** - WPF UI framework for `DependencyProperty`, `UIElement`, `ItemsControl`, `TreeViewItem`, `Keyboard`, `Key` enumeration.
- **System.ComponentModel** - Provides `INotifyPropertyChanged` interface and `PropertyChangedEventHandler` delegate.
- **System.Collections.ObjectModel** - Provides `ObservableCollection<T>`.
### What depends on this module:
- **Unclear from source alone** - No direct consumers are visible in these files. Based on naming conventions and structure, this module is likely consumed by ViewModel classes in `DTS.Viewer.GraphList` and View components displaying TreeViews and PropertyGrids.
---
## 5. Gotchas
1. **Typo in Property Name**: `GraphObject.Visable` is misspelled; should be `Visible`. This typo propagates to any XAML bindings or consuming code.
2. **Dead Code in Constructor**: `GraphObject.LoadGraphs()` contains only commented-out code referencing a `ServiceController`. This method is called from the constructor but performs no operation.
3. **Silent Failures in Selection Logic**:
- `TestGroup.IsSelected` silently returns without setting the value if `Name` starts with "Test Channels" or "Calculated Channels".
- `TestGroup.IsSelected` silently returns if `CanLock` is `false` and attempting to select.
- `TreeViewIds.IsSelected` silently returns if `Parent` is null or cannot be cast to `IExportGraphMainViewModel`.
4. **Complex Selection State Machine**: The selection logic in `TestEvent.SetIsSelected()` relies on multiple interdependent flags on the parent ViewModel. Incorrect flag states could cause selection operations to be silently ignored or applied incorrectly.
5. **Duplicate Static Properties**: `IsShiftPressed` is defined identically in both `TreeViewIds` and `TestEvent` classes.
6. **Get-Only Property**: `IsSaved` in both `TreeViewChannels` and `TreeViewIds` is a get-only property with no backing field initialization, meaning it will always return `false` (default for `bool`).
7. **Type-Safe Cast Risks**: Multiple locations use direct casts to interface types (e.g., `((IExportGraphMainViewModel)Parent)`) without null checks or `as` operator, which could cause `InvalidCastException` or `NullReferenceException` if the parent is not the expected type.
8. **Unused Dependency**: `System.ServiceProcess` is imported in `GraphObject.cs` but only used in commented-out code.

View File

@@ -0,0 +1,45 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:48:48.347905+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "af860c5bc7afa07c"
---
# Documentation: DTS.Viewer.GraphList Assembly Configuration
## 1. Purpose
This file provides assembly-level metadata and configuration for the `DTS.Viewer.GraphList` module (compiled as `Graph.dll`). It defines the assembly's identity, versioning information, and COM visibility settings using standard .NET attributes. This module appears to be a component within the larger DTS Viewer application, specifically handling graph-related functionality.
## 2. Public Interface
This file does not contain executable classes or methods. It exposes the following assembly-level attributes via reflection:
* **`AssemblyTitle`**: Set to `"Graph"`.
* **`AssemblyDescription`**: Empty string.
* **`AssemblyConfiguration`**: Empty string.
* **`AssemblyCompany`**: Empty string.
* **`AssemblyProduct`**: Set to `"Graph"`.
* **`AssemblyCopyright`**: Set to `"Copyright © 2017"`.
* **`AssemblyTrademark`**: Empty string.
* **`AssemblyCulture`**: Empty string.
* **`ComVisible`**: Set to `false`. Prevents types within this assembly from being visible to COM components.
* **`Guid`**: Set to `"61261c58-c32e-4dea-a87a-d7f956f28b4d"`. Acts 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
* **COM Visibility:** The assembly is explicitly configured to hide types from COM components (`ComVisible(false)`). To expose a specific type to COM, this attribute would need to be overridden at the class level.
* **Versioning:** Both the assembly version and file version are fixed at `1.0.0.0`. The automatic versioning syntax (`1.0.*`) is commented out, indicating manual version control.
* **Identity:** The `Guid` is unique to this assembly and constant.
## 4. Dependencies
* **Internal Dependencies:**
* `System.Reflection`: Used for assembly metadata attributes.
* `System.Runtime.CompilerServices`: Included standard using directive.
* `System.Runtime.InteropServices`: Required for the `ComVisible` and `Guid` attributes.
* **External Dependents:** The main `DTS Viewer` application depends on this assembly for Graph-related modules.
## 5. Gotchas
* **Naming Inconsistency:** The `AssemblyTitle` and `AssemblyProduct` are set to `"Graph"`, while the project folder structure suggests the module is named `DTS.Viewer.GraphList`. This may cause confusion when referencing the assembly by name or viewing it in reflection tools.
* **Legacy Project Format:** The existence of this explicit `AssemblyInfo.cs` suggests a classic .NET Framework project format (non-SDK style). Modern .NET Core/5+ projects typically auto-generate this information in the `.csproj` file. If the project is upgraded to SDK-style, this file may cause conflicts with auto-generated attributes unless `<GenerateAssemblyInfo>false</GenerateAssemblyInfo>` is set in the project file.

View File

@@ -0,0 +1,73 @@
---
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-16T13:49:07.805829+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "e0305153f9f5be9f"
---
# Documentation: Graph List Views
## 1. Purpose
This module provides two WPF view components for graph-related functionality within the DTS Viewer application. `ExportGraphMainView` and `GraphMainView` are code-behind partial classes for their respective XAML views, both implementing specific interfaces (`IExportGraphMainView` and `IGraphMainView`) and handling the `ApplicationCommands.Undo` command by marking it as handled. These views appear to be part of a modular architecture for displaying and exporting graph data.
---
## 2. Public Interface
### `ExportGraphMainView` (class, partial)
**Namespace:** `DTS.Viewer.GraphList`
**Implements:** `IExportGraphMainView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public ExportGraphMainView()` | Initializes the component and registers a `CommandBinding` for `ApplicationCommands.Undo` that marks the command as handled in both Execute and CanExecute handlers. |
### `GraphMainView` (class, partial)
**Namespace:** `DTS.Viewer.GraphList`
**Implements:** `IGraphMainView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public GraphMainView()` | Initializes the component and registers a `CommandBinding` for `ApplicationCommands.Undo` that marks the command as handled in both Execute and CanExecute handlers. |
---
## 3. Invariants
- Both views always mark `ApplicationCommands.Undo` as handled (`e.Handled = true`) in both Execute and CanExecute handlers, effectively suppressing default undo behavior.
- Both views call `InitializeComponent()` as the first operation in their constructors (standard WPF partial class pattern).
- Both classes are `partial`, indicating there is corresponding XAML markup that defines their visual structure.
---
## 4. Dependencies
### This module depends on:
- `System.Windows.Input` — Provides `CommandBinding` and `ApplicationCommands` for WPF command routing.
- `DTS.Common.Interface` — Provides `IExportGraphMainView` and `IGraphMainView` interfaces that these views implement.
### What depends on this module:
- **Unclear from source alone.** The interfaces suggest these views are consumed via their respective interfaces, likely by a presenter, view model, or dependency injection container in the broader application.
---
## 5. Gotchas
1. **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.
2. **Commented-out code in `GraphMainView`:** The constructor contains commented references to:
- `root.IsChecked` — suggests a checkbox or toggle control named `root`
- `TvTestChannels.Focus()` — suggests a TreeView or similar control named `TvTestChannels`
- A commented-out method `SetTvFocus()` also references `TvTestChannels`
This indicates incomplete refactoring or legacy functionality that was removed but not cleaned up.
3. **Undo command suppression without action:** Both views suppress the Undo command but perform no actual undo operation. This may be intentional (to prevent undo in these views) or a placeholder for future functionality.
4. **No explicit CanExecute result:** The CanExecute handlers set `e.Handled = true` but do not set `e.CanExecute`. The default behavior of `e.CanExecute` when not explicitly set is unclear from this source alone.

View File

@@ -0,0 +1,83 @@
---
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.