Files
DP44/enriched-qwen3-coder-next/DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/ViewModel.md
2026-04-17 14:55:32 -04:00

8.4 KiB

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/ViewModel/GraphMainViewModel.cs
2026-04-16T13:48:30.268564+00:00 zai-org/GLM-5-FP8 1 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.