Files
2026-04-17 14:55:32 -04:00

253 lines
12 KiB
Markdown

---
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.