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,74 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/AddCalculatedChannelModule.cs
generated_at: "2026-04-16T13:45:51.254810+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "a6eff6c72a8470eb"
---
# Documentation: DTS.Viewer.AddCalculatedChannel Module
## 1. Purpose
This module serves as the entry point for the "Add Calculated Channel" feature within the DTS Viewer application. It is responsible for self-registering its View and ViewModel components with the Unity dependency injection container and providing assembly-level metadata (such as display name, icon, and region assignment) to the main application shell for module discovery and UI composition.
## 2. Public Interface
### `AddCalculatedChannelModule`
The main Prism module class responsible for dependency registration.
* **`AddCalculatedChannelModule(IUnityContainer unityContainer)`**
* Constructor that accepts an `IUnityContainer` instance via dependency injection and stores it in a private readonly field `_unityContainer`.
* **`void RegisterTypes(IContainerRegistry containerRegistry)`**
* Implements `IModule.RegisterTypes`. Calls the private `Initialize()` method to perform type registrations.
* **`void OnInitialized(IContainerProvider containerProvider)`**
* Implements `IModule.OnInitialized`. Currently contains no implementation logic.
### `AddCalculatedChannelModuleNameAttribute`
An assembly-level attribute used to expose the module's name.
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.AddCalculatedChannel`.
* **`Type GetAttributeType()`**
* Returns `typeof(TextAttribute)`.
* **`string GetAssemblyName()`**
* Returns the value of the `AssemblyName` property.
### `AddCalculatedChannelModuleImageAttribute`
An assembly-level attribute used to expose the module's image, group, and region metadata.
* **`BitmapImage AssemblyImage { get; }`**
* Retrieves the module's icon using `AssemblyInfo.GetImage`.
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.AddCalculatedChannel`.
* **`string AssemblyGroup { get; }`**
* Returns `eAssemblyGroups.Viewer.ToString()`.
* **`eAssemblyRegion AssemblyRegion { get; }`**
* Returns `eAssemblyRegion.AddCalculatedChannelRegion`.
* **`BitmapImage GetAssemblyImage()` / `string GetAssemblyName()` / `string GetAssemblyGroup()` / `eAssemblyRegion GetAssemblyRegion()`**
* Accessor methods returning the values of their corresponding properties.
## 3. Invariants
* **Naming Consistency:** The `AssemblyName` property in both attribute classes must always resolve to `AssemblyNames.AddCalculatedChannel.ToString()`.
* **Region Assignment:** The module is strictly assigned to the `eAssemblyRegion.AddCalculatedChannelRegion` region.
* **Group Assignment:** The module belongs strictly to the `eAssemblyGroups.Viewer` group.
* **Registration Mapping:** The `Initialize` method maps the interface `IAddCalculatedChannelView` to the concrete implementation `AddCalculatedChannelView`, and `IAddCalculatedChannelViewModel` to `AddCalculatedChannelViewModel`.
## 4. Dependencies
### Internal Dependencies
* **`DTS.Common`**: Used for `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, and `AssemblyInfo`.
* **`DTS.Common.Interface`**: Provides the base classes `TextAttribute` and `ImageAttribute`.
* **`DTS.Viewer.AddCalculatedChannel`**: The module references concrete types `AddCalculatedChannelView` and `AddCalculatedChannelViewModel` defined within its own scope (though the file defining them is not provided here, they are referenced in `Initialize`).
### External Dependencies
* **`Prism.Ioc`**: Provides `IContainerProvider` and `IContainerRegistry`.
* **`Prism.Modularity`**: Provides `IModule` and `ModuleAttribute`.
* **`Unity`**: Provides `IUnityContainer` (used for specific Unity registration methods).
* **`System.Windows.Media.Imaging`**: Provides `BitmapImage` for image handling.
## 5. Gotchas
* **Misleading Singleton Comment:** The comment in `Initialize()` states: *"Register View & View-Model with Unity dependency injection container as a singleton."* However, the code uses `_unityContainer.RegisterType<...>()`. In Unity, `RegisterType` registers a transient mapping (new instance per request) by default, not a singleton. To register as a singleton, `ContainerControlledLifetimeManager` should be used. The code behavior contradicts the documentation.
* **Side Effects in Property Getters:** In `AddCalculatedChannelModuleImageAttribute`, the getter for `AssemblyImage` modifies the private field `_img` (lazy initialization pattern inside a property getter). This is a side effect that could cause unexpected behavior if the property is accessed multiple times or inspected in a debugger, though the result is cached.
* **Unused Constructor Parameter:** Both attribute classes define a constructor taking a `string s`, but the parameter is never used inside the constructor body. This suggests the parameter exists solely to satisfy a reflection-based instantiation requirement or is legacy code.
* **Dual Registration Approach:** The module uses `IUnityContainer` (field injection) to call `RegisterType`, but the `RegisterTypes` method signature provides an `IContainerRegistry`. This mixes Prism's abstract container registry with the concrete Unity container. While valid if the backing container is Unity, it couples the module strictly to the Unity container rather than remaining container-agnostic.

View File

@@ -0,0 +1,119 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/Model/CalculatedChannelCreator.cs
generated_at: "2026-04-16T13:59:32.414209+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "d05bf6b72e9c97be"
---
# CalculatedChannelCreator Documentation
## 1. Purpose
The `CalculatedChannelCreator` class is a factory responsible for creating derived data channels from existing sensor input channels. It supports three categories of calculations: 3D IR-Tracc displacement calculations (Thorax, Abdomen, LowerThorax variants), aggregate operations across multiple channels (SUM, AVE, Resultant, HIC), and single-channel binary operations (Integral, DoubleIntegral, Derivative, Sin, Cos). The class handles sample rate alignment via interpolation, creates persistent file-backed channel storage, and manages the full lifecycle of calculated channel creation including validation, computation, scaling, and serialization.
## 2. Public Interface
### `CreateChannels`
```csharp
public static Test.Module.CalculatedChannel[] CreateChannels(
string testId,
string folder,
Calculation calculation,
List<Test.Module.Channel> inputChannels,
string channelName,
int startingNumber,
List<Test.Module.Channel> allChannels,
int clipLength,
out List<string> errorList,
int defaultEncoding)
```
**Behavior:** Main entry point for creating calculated channels. Dispatches to appropriate private creation methods based on the `Calculation` enum value. Returns an array of `Test.Module.CalculatedChannel` objects or `null` on failure. Validates channel names before returning. Sets `AbsoluteDisplayOrder` on each created channel.
### `ValidateChannelName`
```csharp
public static bool ValidateChannelName(
string channelName,
List<Test.Module.Channel> inputChannels,
List<Test.Module.Channel> allChannels,
out List<string> errorList)
```
**Behavior:** Validates that the channel name is non-empty and unique across both input channels and all channels. Returns `true` if validation passes (empty error list). If `allChannels` is `null`, returns `true` immediately with empty error list (special case for calls from `MakeCalculatedChannels()` in Download.xaml.cs per source comments).
### `ThreeDIRTraccType` (enum)
```csharp
public enum ThreeDIRTraccType
{
Thorax,
Abdomen,
LowerThorax
}
```
**Behavior:** Defines the three anatomical positions for 3D IR-Tracc sensor calculations, each using different constants (`δ` and `D0`) from `SensorConstants`.
## 3. Invariants
- **Channel Number Indicator:** All calculated channels use `ChannelNumberCalculationChannelIndicator` (100000) as a base offset for channel numbering.
- **3D IR-Tracc Input Count:** Must have exactly 3 input channels (enforced by `Trace.Assert`).
- **Aggregate Operation Input Count:** Must have at least 1 input channel (enforced by `Trace.Assert` for SUM/AVE/Resultant/HIC).
- **Sample Rate Divisibility:** The maximum sample rate among input channels must be a multiple of all other input channel sample rates; otherwise `NotSupportedException` is thrown.
- **Super-sampling Notification:** When input channels have different sample rates, a `PageErrorEvent` with `SuperSamplingWarning` is published via `IEventAggregator`.
- **Data Scaling:** Output data is scaled to fit within `short.MaxValue` range for ADC representation.
- **Engineering Units:** 3D IR-Tracc output channels use "mm" as engineering units; Sin/Cos use "rads".
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Enums.Sensors` - `SensorConstants` for IR-Tracc physical constants
- `DTS.Common.Utilities.Logging` - `APILogger` for file operation logging
- `DTS.Common.Utils` - `FileUtils` for file deletion
- `DTS.Serialization` - `Serialization.SliceRaw.File` and related types for persistent storage
- `DTS.Slice.Control` - Unclear specific usage from source alone
- `DTS.Common` - `Constants.ADC_MIDPOINT`, `ZeroMethodType`
- `DTS.Common.Events` - `PageErrorEvent`, `PageErrorArg`
- `DTS.Common.Calculations` - `HeadInjuryCriterion` for HIC calculations
- `DTS.Common.Utilities.Math.Nhtsa` - `Integration`, `Differentiation` classes
- `Prism.Ioc` - `ContainerLocator` for service location
- `Prism.Events` - `IEventAggregator` for event publishing
- `Test.Module` namespace - `Channel`, `CalculatedChannel`, `AnalogInputChannel`
- `Event.Module` namespace - `Channel`, `AnalogInputChannel` (EMC layer)
### What Depends On This Module:
- Unclear from source alone; callers are external to this file.
## 5. Gotchas
### Critical Bug in `CreateChannels` Return Logic
Lines 54-57 contain inverted logic:
```csharp
if (ValidateChannelName(channelName, inputChannels, allChannels, out errorList)) return calculatedChannels;
//ReportErrors(errorList);
return null;
```
The method returns `calculatedChannels` when validation **succeeds** but then immediately returns `null` afterward (unreachable code for the error path). The commented-out `ReportErrors` suggests incomplete error handling. The intent appears reversed—validation failure should likely return `null`.
### Copy-Paste Bug in `PerformCalculation`
Line 388 calculates `stepRPot1` using the wrong index variable:
```csharp
var stepRPot1 = Convert.ToInt32(Math.Ceiling(indexAtCurrentTimeIRTracc) - actualIndexAtCurrentTimeIRTracc);
```
This should likely use `indexAtCurrentTimeRPot1` instead of `indexAtCurrentTimeIRTracc`.
### Assignment in Conditional (Line 398)
```csharp
incrementRPot2 = (valueRPot2AtPoint = rPot2EUData[actualIndexAtCurrentTimeRPot2 - 1]) / rateRPot2;
```
This assigns to `valueRPot2AtPoint` inside a conditional branch, which differs from the parallel IRTracc and RPot1 branches that only read the value.
### Explicit GC Collection
`CreatePersistentInformationObject` calls `GC.Collect()` before file deletion to release memory-mapped file handles—a potential performance concern.
### Debug/Test Data Injection
`PerformCalculation` calls `DiskUtility.ReplaceDataIfNeeded` with hardcoded filenames ("DISPLEU.txt", "YPOTEU.txt", "ZPOTEU.txt"), suggesting debug/override capability that may affect production behavior.
### HIC Unit Conversion
`PerformCalculationsAggregate` converts m/s² to g's (multiplying by 9.80665) for HIC calculations when engineering units are not already "g", but this conversion is applied inconsistently—only to `dataAtPoint` for the `dSumSquares` calculation, not to `dAggregateValue`.
### Unused Variable
Line 246 declares `var timeAtIndex =` with no assignment or usage.

View File

@@ -0,0 +1,40 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:59:10.185944+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "013fcfe349498337"
---
# Documentation: DTS.Viewer.AddCalculatedChannel Assembly Configuration
## 1. Purpose
This source file provides assembly-level metadata and configuration for the `DTS.Viewer.AddCalculatedChannel` module. It serves as the identity manifest for the compiled binary, defining its title, version, copyright, and COM visibility settings. Based on the assembly name, this module appears to be a plugin or component within the larger DTS Viewer application responsible for functionality related to adding derived or computed data channels.
## 2. Public Interface
This file contains no executable classes, methods, or functions. It consists entirely of assembly-level attributes used by the .NET runtime and build system.
* **`AssemblyTitle`**: Set to `"DTS.Viewer.AddCalculatedChannel"`.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.AddCalculatedChannel"`.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
* **`Guid`**: Set to `"6451f3ed-934e-47e3-a1ca-33c223a6507a"`.
* **`ComVisible`**: Set to `false`.
## 3. Invariants
* **COM Visibility:** The types within this assembly are never visible to COM components (`ComVisible` is explicitly `false`).
* **Culture Neutrality:** The assembly is marked with an empty `AssemblyCulture`, indicating it is culture-neutral and not a satellite assembly.
* **Versioning:** Both the assembly version and file version are currently locked to the specific quadruple `1.0.0.0`.
## 4. Dependencies
* **Internal Dependencies:**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* **External Consumers:** The compiled assembly produced by this project is likely consumed by the main `DTS Viewer` application or a plugin loader, though specific consumers cannot be determined from this file alone.
## 5. Gotchas
* **Missing Description:** The `AssemblyDescription` attribute is an empty string. Developers cannot rely on assembly metadata to understand the purpose of this module; they must inspect the code or external documentation.
* **Static Versioning:** The `AssemblyVersion` and `AssemblyFileVersion` are hardcoded to `1.0.0.0`. They do not use the wildcard syntax (`"1.0.*"`) to auto-generate build/revision numbers, which may require manual updating for future releases.
* **Legacy Project Structure:** The presence of a standalone `AssemblyInfo.cs` file suggests this is a legacy .NET Framework project structure (prior to the SDK-style project format introduced in .NET Core/5+), where this information is typically auto-generated.

View File

@@ -0,0 +1,145 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:58:32.085292+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "5726c0d4d71935f1"
---
# Documentation: DTS.Viewer.AddCalculatedChannel.Resources
## 1. Purpose
This module provides localization infrastructure for the "Add Calculated Channel" feature within the DTS Viewer application. It enables XAML-based UI elements to bind to localized strings at design-time and runtime through a WPF markup extension pattern, while the `StringResources` class serves as a strongly-typed accessor for culture-specific strings related to calculation types, channel operations, IR-TRACC measurements, and validation error messages.
---
## 2. Public Interface
### TranslateExtension (MarkupExtension)
**Class Definition:**
```csharp
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
```
**Constructor:**
```csharp
public TranslateExtension(string key)
```
Initializes the extension with a resource key to look up.
**Method:**
```csharp
public override object ProvideValue(IServiceProvider serviceProvider)
```
Returns the localized string for the provided `_key`. Returns `#stringnotfound#` if `_key` is null or empty. Returns `#stringnotfound# <key>` (where `<key>` is the actual key value) if the resource manager returns null for the given key.
---
### StringResources (Auto-generated Resource Class)
**Class Definition:**
```csharp
internal class StringResources
```
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `ResourceManager` | `global::System.Resources.ResourceManager` (static) | Cached ResourceManager instance for the `DTS.Viewer.AddCalculatedChannel.Resources.StringResources` resource bundle |
| `Culture` | `global::System.Globalization.CultureInfo` (static) | Gets or sets the current thread's CurrentUICulture for resource lookups |
**Resource String Properties (static, read-only):**
| Property Name | Default Value (from comments) |
|---------------|-------------------------------|
| `AddCalculatedChannel` | "Add Calculated Channel" |
| `CalculatedChannel_Average` | "Average" |
| `CalculatedChannel_Sum` | "Sum" |
| `CalculatedChannel_IRTRACC3D` | "3D IR-TRACC (upper thorax)" |
| `CalculatedChannel_IRTRACC3D_Abdomen` | "3D IR-TRACC (abdomen)" |
| `CalculatedChannel_IRTRACC3D_LowerThorax` | "3D IR-TRACC (lower thorax)" |
| `CalculatedChannel_IRTRACC3D_Thorax` | "3D IR-TRACC (thorax)" |
| `CalculatedChannel_IRTRACC3DAbdomen` | "3D IR-TRACC (abdomen)" |
| `CalculatedChannel_IRTRACC3DLowerThorax` | "3D IR-TRACC (lower thorax)" |
| `Calculation` | "Calculation" |
| `CALCULATION_Cos` | "Cosine" |
| `CALCULATION_Derivative` | "Derivative" |
| `CALCULATION_DoubleIntegral` | "Double integral" |
| `CALCULATION_Integral` | "Integral" |
| `CALCULATION_Sin` | "Sine" |
| `CALCULATION_ThreeDIRTracc` | "3D IR-TRACC (upper thorax)" |
| `CALCULATION_ThreeDIRTraccAbdomen` | "3D IR-TRACC (abdomen)" |
| `CALCULATION_ThreeDIRTraccLowerThorax` | "3D IR-TRACC (lower thorax)" |
| `CalculationInputChannel` | "Calculation Input Channel" |
| `Channel` | "Channel" |
| `ChannelName` | "Channel Name" |
| `ClipLengthMS` | "Clip length (ms)" |
| `Description` | "Description" |
| `HICAccelerationX` | "Acceleration X" |
| `HICAccelerationY` | "Acceleration Y" |
| `HICAccelerationZ` | "AccelerationZ" |
| `HICRequires3Channels` | "Error: Head injury criterion requires 3 channels." |
| `InputChannels` | "Input channels" |
| `ISOCode` | "ISO Code" |
| `NoChannelsIncluded` | "Error: No channels included." |
| `ResultantUnitsDontMatch` | "Error: Units don't match for all input channels." |
| `SampleRatesDontMatch` | "Error: Sample rates don't match for all input channels." |
| `SuperSamplingWarning` | "Calculation contains multiple sample rates. Input will be resampled to the highest sample rate using linear interpolation." |
| `ThreeD_IRTracc` | "IR-TRACC" |
| `ThreeD_RotPot1` | "R. Pot Y" |
| `ThreeD_RotPot2` | "R. Pot Z" |
---
## 3. Invariants
- **TranslateExtension return guarantee:** `ProvideValue` always returns a non-null `string` object; it never returns null.
- **Error indicator format:** Missing keys are indicated by the constant `#stringnotfound#` (exact literal, lowercase), optionally followed by a space and the key name.
- **StringResources visibility:** The `StringResources` class is `internal` and only accessible within the `DTS.Viewer.AddCalculatedChannel` assembly.
- **Auto-generation constraint:** `StringResources.Designer.cs` is auto-generated by `System.Resources.Tools.StronglyTypedResourceBuilder` (version 17.0.0.0). Manual edits will be lost upon regeneration.
- **Resource bundle path:** Resources are loaded from the manifest resource name `"DTS.Viewer.AddCalculatedChannel.Resources.StringResources"`.
---
## 4. Dependencies
### This module depends on:
- `System` (core types)
- `System.Windows.Markup` (for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute`)
- `System.Resources` (for `ResourceManager`)
- `System.Globalization` (for `CultureInfo`)
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices`, `System.ComponentModel`, `System.Diagnostics.CodeAnalysis` (for auto-generated attributes)
### What depends on this module:
- **Inferred:** XAML files within the `DTS.Viewer.AddCalculatedChannel` namespace that use the `{local:Translate KeyName}` markup extension syntax for localized UI strings.
- **Inferred:** Code-behind files that reference `StringResources.<PropertyName>` for error messages and labels.
---
## 5. Gotchas
1. **Duplicate/near-duplicate resource keys:** Several IR-TRACC-related strings exist with different naming conventions that produce identical default values:
- `CalculatedChannel_IRTRACC3D_Abdomen` and `CalculatedChannel_IRTRACC3DAbdomen` both default to "3D IR-TRACC (abdomen)"
- `CalculatedChannel_IRTRACC3D_LowerThorax` and `CalculatedChannel_IRTRACC3DLowerThorax` both default to "3D IR-TRACC (lower thorax)"
- `CALCULATION_ThreeDIRTracc` and `CalculatedChannel_IRTRACC3D` both default to "3D IR-TRACC (upper thorax)"
This may indicate a naming convention migration or accidental duplication. The source alone does not clarify which keys are actively used.
2. **Inconsistent key naming conventions:** Resource keys use at least three different naming patterns:
- `PascalCase` (e.g., `Channel`, `Description`)
- `Category_Property` (e.g., `CalculatedChannel_Average`)
- `CATEGORY_Property` (e.g., `CALCULATION_Sin`, `CALCULATION_Derivative`)
Developers adding new keys should verify which convention is expected.
3. **Typo in HICAccelerationZ:** The default value is "AccelerationZ" (no space), whereas `HICAccelerationX` and `HICAccelerationY` have spaces ("Acceleration X", "Acceleration Y"). This inconsistency is visible in the source comments.
4. **NotFound constant is private:** The `NotFound` constant in `TranslateExtension` is `private const string`, so consumers cannot reference it for comparison. The literal `#stringnotfound#` would need to be hardcoded for string comparison checks.
5. **No null-coalescing on empty string:** `ProvideValue` checks `string.IsNullOrEmpty(_key)`, returning `NotFound` without appending the key. However, if `_key` is an empty string, the caller receives `#stringnotfound#` without indication that an empty string was passed.

View File

@@ -0,0 +1,38 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/View/AddCalculatedChannelView.xaml.cs
generated_at: "2026-04-16T13:59:47.969397+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "13409539a2c3243c"
---
# Documentation: AddCalculatedChannelView.xaml.cs
## 1. Purpose
This file defines the code-behind class `AddCalculatedChannelView` for a WPF XAML user interface component. It serves as the visual view for the "Add Calculated Channel" feature within the DTS Viewer application. Its primary role is to implement the `IAddCalculatedChannelView` interface, allowing it to be consumed by other components (likely a presenter or view model) while handling the initialization of the XAML component tree.
## 2. Public Interface
### Class: `AddCalculatedChannelView`
- **Inheritance:** Implements `IAddCalculatedChannelView`.
- **Modifiers:** `public`, `partial`.
#### Constructor: `AddCalculatedChannelView()`
- **Signature:** `public AddCalculatedChannelView()`
- **Behavior:** Calls `InitializeComponent()`, which loads and initializes the XAML-defined UI layout associated with this code-beind file.
## 3. Invariants
- **Partial Definition:** The class is defined as `partial`. A corresponding XAML file (`AddCalculatedChannelView.xaml`) must exist to provide the other part of the class definition (typically defining the base class and UI elements).
- **Interface Compliance:** The class must fulfill any contract defined by `IAddCalculatedChannelView` (imported from `DTS.Common.Interface`), though no explicit interface members are visible in this specific source file.
## 4. Dependencies
- **External Dependencies:**
- `DTS.Common.Interface`: Required for the `IAddCalculatedChannelView` interface.
- **Implicit Dependencies:**
- WPF Subsystem: Relies on `InitializeComponent()`, a standard method usually generated by the WPF build process.
- `AddCalculatedChannelView.xaml`: The markup file corresponding to this code-behind.
## 5. Gotchas
- **Namespace Mismatch:** The source contains `// ReSharper disable CheckNamespace`. This directive suppresses the IDE warning that the namespace `DTS.Viewer.AddCalculatedChannel` does not match the file path structure (`DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/View/`). Developers should be aware that the namespace is intentionally flattened or differs from the folder hierarchy.
- **Hidden Base Class:** The C# code shows the class inheriting from `IAddCalculatedChannelView`. In a standard WPF setup, the class would also inherit from a base class like `UserControl` or `Window`. This inheritance is typically defined in the root element of the XAML file, not the C# `class` declaration. Therefore, the concrete UI base type is not visible in this source file alone.

View File

@@ -0,0 +1,215 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/ViewModel/AddCalculatedChannelViewModel.cs
generated_at: "2026-04-16T13:58:53.491336+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "5cfd5d272102b3bf"
---
# Documentation: AddCalculatedChannelViewModel
## 1. Purpose
The `AddCalculatedChannelViewModel` class provides the presentation logic for creating and adding calculated channels to test data within the DTS Viewer application. It supports multiple calculation types including mathematical operations (Integral, Double Integral, Derivative, Sin, Cos), aggregate functions (SUM, Average, Resultant), and specialized biomechanical calculations (3D IR-Tracc variants, HIC - Head Injury Criterion). The ViewModel manages channel selection UI state, validates user inputs, persists calculated channels to `.dts` test files, and coordinates with the event aggregation system for cross-component communication.
---
## 2. Public Interface
### Class Declaration
```csharp
public class AddCalculatedChannelViewModel : BaseViewModel<IAddCalculatedChannelViewModel>, IAddCalculatedChannelViewModel
```
### Constructor
```csharp
public AddCalculatedChannelViewModel(IAddCalculatedChannelView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the ViewModel with its associated view, region manager for UI composition, event aggregator for pub/sub messaging, and Unity dependency injection container.
### Public Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IBaseView` | The associated view instance; DataContext is set to `this` in constructor. |
| `Parent` | `IBaseViewModel` | Parent ViewModel passed during initialization. |
| `ContextSearchRegion` | `object` | Context region placeholder. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Raises notification dialogs. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Raises confirmation dialogs (hides base member). |
| `HeaderInfo` | `string` | Returns `"AddCalculatedChannelRegion"`. |
| `IsBusy` | `bool` | Throws `NotImplementedException` on get/set. |
| `IsDirty` | `bool` | Throws `NotImplementedException` on get. |
| `IsAddCalculatedChannelIncluded` | `bool` | Feature inclusion flag. |
| `IncludeGroupNameInISOExport` | `bool` | Controls ISO export format. |
| `DefaultDTSEncoding` | `int` | Encoding codepage for DTS file operations. |
| `ChannelName` | `string` | Name for the new calculated channel. |
| `ChannelDescription` | `string` | Auto-generated description based on selected calculation and channels. |
| `IsoCode` | `string` | ISO code identifier; defaults to `"NONE"`. |
| `SingleChannelSelectorVisibility` | `bool` | Controls visibility for single-channel selection UI. |
| `MultipleChannelSelectorVisibility` | `bool` | Controls visibility for multi-channel selection UI. |
| `HICChannelSelectorVisibility` | `bool` | Controls visibility for HIC-specific channel selection. |
| `ThreeDIRTRACCVisibility` | `bool` | Controls visibility for 3D IR-Tracc channel selection. |
| `CalculationList` | `CalculationHelper[]` | Lazy-initialized list of available calculations. |
| `SelectedCalculation` | `CalculationHelper` | Currently selected calculation type; setter updates UI visibility states. |
| `ChannelList` | `ObservableCollection<ITestChannel>` | All available input channels. |
| `ChannelListObjects` | `ObservableCollection<ChannelHelper>` | Wrapped channel objects with inclusion tracking. |
| `SourceChannel` | `ITestChannel` | Selected source channel for single-channel calculations. |
| `AvailableHICChannels` | `ChannelHelper[]` | Channels with acceleration units valid for HIC calculation. |
| `HICAccelerationX` | `ChannelHelper` | X-axis acceleration channel for HIC. |
| `HICAccelerationY` | `ChannelHelper` | Y-axis acceleration channel for HIC. |
| `HICAccelerationZ` | `ChannelHelper` | Z-axis acceleration channel for HIC. |
| `HICLength` | `int` | HIC calculation length parameter; defaults to `16`. |
| `IRTraccChannelList` | `ObservableCollection<ChannelHelper>` | Valid IR-Tracc channels. |
| `IRTraccChannel` | `ChannelHelper` | Selected IR-Tracc channel. |
| `Pot1ChannelList` | `ObservableCollection<ChannelHelper>` | Valid potentiometer 1 channels. |
| `Pot1Channel` | `ChannelHelper` | Selected potentiometer 1 channel. |
| `Pot2ChannelList` | `ObservableCollection<ChannelHelper>` | Valid potentiometer 2 channels. |
| `Pot2Channel` | `ChannelHelper` | Selected potentiometer 2 channel. |
### Public Methods
```csharp
public void PublishChanges()
```
Empty implementation (commented `NotImplementedException`).
```csharp
public override void Initialize()
public override void Initialize(object parameter)
```
Sets `Parent` from parameter and subscribes to events.
```csharp
public override void Activated()
```
Resets UI state: sets default `SourceChannel`, `IsoCode` to `"NONE"`, `ChannelName` to `"New Channel"`, clears HIC selections, sets `HICLength` to `16`.
```csharp
public override void Cleanup()
```
Empty implementation.
```csharp
public bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)
```
Validates channel name and calculation-specific requirements (HIC requires 3 channels; Resultant requires matching units and sample rates).
```csharp
public bool ValidateChannelName()
```
Returns `true` if `ChannelName` is non-empty.
### Commands
```csharp
public ICommand AddCalculatedChannelCommand { get; private set; }
```
Executes `AddCalculatedChannel(object obj)` which validates input, creates calculated channels via `CalculatedChannelCreator.CreateChannels()`, adds them to the test structure, and persists changes to `.dts` files.
### Public Enum
```csharp
public enum Calculation
{
[Description("Integral")] Integral = 0,
[Description("Double Integral")] DoubleIntegral = 1,
[Description("Derivative")] Derivative = 2,
[Description("Sin")] Sin = 3,
[Description("Cos")] Cos = 4,
[Description("3D IR-Tracc")] ThreeDIRTracc = 5,
[Description("SUM")] SUM = 6,
[Description("Average")] AVE = 7,
[Description("3D IR-TRACC Abdomen")] ThreeDIRTraccAbdomen = 8,
[Description("3D IR-TRACC Lower Thorax")] ThreeDIRTraccLowerThorax = 9,
[Description("Resultant")] Resultant = 10,
[Description("HIC")] HIC = 11
}
```
### Nested Public Classes
```csharp
public class ChannelHelper : BasePropertyChanged
```
Wraps `ITestChannel` with `DisplayName`, `ChannelName`, and `IsIncluded` properties for UI binding.
```csharp
public class CalculationHelper
```
Wraps `Calculation` enum with localized `ToString()` via resource manager.
---
## 3. Invariants
1. **Channel Name Validation**: `ChannelName` must be non-null and non-empty for validation to pass.
2. **HIC Channel Requirement**: HIC calculation requires all three acceleration channels (`HICAccelerationX`, `HICAccelerationY`, `HICAccelerationZ`) to be non-null.
3. **Resultant Channel Consistency**: All channels included in a Resultant calculation must have identical `SensitivityUnits` and `SampleRateHz`.
4. **Display Order Preservation**: Channels are sorted by `AbsoluteDisplayOrder` when determining insertion position for new calculated channels.
5. **File Backup Behavior**: Backup files (`.dtsbak`) are created only if one does not already exist; original file is preserved.
6. **IR-Tracc Channel Eligibility**: IR-Tracc channels must be `AnalogInputChannel` type with valid `LinearizationFormula`, `ZeroMethod` of `None`, non-zero `ZeroPoint`, and non-zero `FactoryExcitationVoltage`.
7. **Potentiometer Channel Eligibility**: Pot channels must be `AnalogInputChannel` type with units `"deg"` or `"deg-ang"`, `ZeroMethod` of `None`, and non-zero `FactoryExcitationVoltage`.
8. **HIC Channel Filtering**: Only channels with units in `Constants.ACCELERATION_UNITS` are available for HIC selection.
---
## 4. Dependencies
### External Dependencies (from imports)
- `Prism.Events` - `IEventAggregator` for event pub/sub
- `Prism.Regions` - `IRegionManager` for UI region management
- `Unity` - `IUnityContainer` for dependency injection
- `DTS.Serialization.Test` - Test data structures
- `DTS.Serialization.SliceRaw.File` - File I/O for `.dts` files
### Internal Dependencies
- `DTS.Common` / `DTS.Common.Base` - Base classes, constants
- `DTS.Common.Classes.Viewer.Commands` - `RelayCommand`
- `DTS.Common.DAS.Concepts` - `ITestChannel` interface
- `DTS.Common.Enums.Sensors` - `ZeroMethodType`
- `DTS.Common.Events` - Event types (`RaiseNotification`, `TestSummaryChangeNotification`, `PageErrorEvent`, `SetSaveButton`, `RefreshTestRequestEvent`)
- `DTS.Common.Interactivity` - `InteractionRequest<T>`, `Notification`, `Confirmation`
- `DTS.Common.Interface` - `IAddCalculatedChannelView`, `IAddCalculatedChannelViewModel`
- `DTS.Common.Utilities.Logging` - `APILogger`
- `DTS.Common.Utils` - `Utils` static helpers
- `DTS.Slice.Control` - Slice control functionality
- `DTS.Viewer.AddCalculatedChannel.Model` - `CalculatedChannelCreator`, `LinearizationFormula`
### Events Consumed
- `RaiseNotification` - Displays notification dialogs
- `TestSummaryChangeNotification` - Triggers channel list population
### Events Published
- `PageErrorEvent` - Publishes validation errors/warnings
- `SetSaveButton` - Controls save button enabled state
- `RefreshTestRequestEvent` - Triggers test data refresh after save
- `RaiseNotification` - Displays error messages
---
## 5. Gotchas
1. **NotImplementedException on IsBusy/IsDirty**: Both properties throw on access. These appear to be placeholder implementations that were never completed.
2. **HIC Save Button Logic Appears Inverted**: In `UpdateSaveButtonVisibility()`, the HIC case sets `IsUsable = true` when channels are null and `IsUsable = false` when all three are set—the opposite of expected behavior:
```csharp
if (null == HICAccelerationX || null == HICAccelerationY || null == HICAccelerationZ)
{
_eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = true });
}
else
{
_eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = false });
}
```
3. **Member Hiding with `new` Keyword**: Several members (`PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`, `ConfirmationRequest`) hide base class members using `new`, which may cause confusion when casting to base types.
4. **Empty PublishChanges() Method**: The `PublishChanges()` method has a commented-out `NotImplementedException` with no implementation, suggesting incomplete feature work.
5. **Hardcoded Thread.Sleep**: A 10ms `Thread.Sleep()` is used after file write operations in `AddCalculatedChannel()`—this is a potential code smell for file I/O timing issues.
6. **Test ID Extraction Fragility**: `GetTestIdFromBinaryFileName()` parses the test ID from binary filenames by looking for `"Ch"` substring; if not found, it uses the entire prefix which may produce incorrect results.
7. **Duplicate Channel Handling**: When adding a calculated channel, existing channels with the same `ChannelId` are silently removed without user confirmation (logged only).

View File

@@ -0,0 +1,94 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/ChartOptionsModule.cs
generated_at: "2026-04-16T13:44:59.673795+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "bcd5ac559d7f6d8e"
---
# Documentation: ChartOptionsModule.cs
## 1. Purpose
This module serves as the Prism module initializer for the `DTS.Viewer.ChartOptions` component within the DTS Viewer application. It is responsible for registering chart options-related views, view models, and models with the Unity dependency injection container, and provides assembly-level metadata (name, image, group, region) that the main application uses to discover and display this module as an available component.
---
## 2. Public Interface
### `ChartOptionsModule` Class
Implements `Prism.Modularity.IModule`. The primary module entry point.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ChartOptionsModule(IUnityContainer unityContainer)` | Accepts an injected Unity container reference. |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Registers types with the container. Calls `Initialize()`. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Empty implementation (no post-initialization logic). |
| `Initialize` | `void Initialize()` | Registers `IChartOptionsView``ChartOptionsView`, `IChartOptionsViewModel``ChartOptionsViewModel`, and `IChartOptionsModel``ChartOptionsModel` with Unity. |
### `ChartOptionsModuleNameAttribute` Class
Extends `TextAttribute`. Applied at assembly level to provide the module's display name.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ChartOptionsModuleNameAttribute()` | Default constructor. |
| Constructor | `ChartOptionsModuleNameAttribute(string s)` | Overload accepting a string (parameter is unused). |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `AssemblyNames.ChartOptions.ToString()`. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(TextAttribute)`. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns the `AssemblyName` property value. |
### `ChartOptionsModuleImageAttribute` Class
Extends `ImageAttribute`. Applied at assembly level to provide module image and categorization metadata.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ChartOptionsModuleImageAttribute()` | Default constructor. |
| Constructor | `ChartOptionsModuleImageAttribute(string s)` | Overload accepting a string (parameter is unused). |
| `AssemblyImage` | `override BitmapImage AssemblyImage { get; }` | Lazily loads image via `AssemblyInfo.GetImage(AssemblyNames.ChartOptions.ToString())`. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `AssemblyNames.ChartOptions.ToString()`. |
| `AssemblyGroup` | `override string AssemblyGroup { get; }` | Returns `eAssemblyGroups.Viewer.ToString()`. |
| `AssemblyRegion` | `override eAssemblyRegion AssemblyRegion { get; }` | Returns `eAssemblyRegion.ChartOptionsRegion`. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(ImageAttribute)`. |
| `GetAssemblyImage` | `override BitmapImage GetAssemblyImage()` | Returns `AssemblyImage` property. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property. |
| `GetAssemblyGroup` | `override string GetAssemblyGroup()` | Returns `AssemblyGroup` property. |
| `GetAssemblyRegion` | `override eAssemblyRegion GetAssemblyRegion()` | Returns `AssemblyRegion` property. |
---
## 3. Invariants
- **Single Instance per Attribute Type**: Both `ChartOptionsModuleNameAttribute` and `ChartOptionsModuleImageAttribute` are decorated with `AllowMultiple = false`, ensuring only one of each can be applied to the assembly.
- **Fixed Assembly Name**: The `AssemblyName` property in both attribute classes is read-only and always returns `AssemblyNames.ChartOptions.ToString()`.
- **Fixed Group Assignment**: The module is always assigned to the `Viewer` assembly group.
- **Fixed Region Assignment**: The module is always assigned to `eAssemblyRegion.ChartOptionsRegion`.
- **Container Registration**: The module always registers the same three interface-to-concrete-type mappings during initialization.
---
## 4. Dependencies
### This Module Depends On:
- **Prism Libraries**: `Prism.Ioc`, `Prism.Modularity` (for `IModule`, `IContainerProvider`, `IContainerRegistry`)
- **Unity**: `Unity` (for `IUnityContainer`)
- **WPF**: `System.Windows.Media.Imaging` (for `BitmapImage`)
- **DTS.Common**: Likely contains `AssemblyNames` enum, `eAssemblyGroups` enum, `eAssemblyRegion` enum, and `AssemblyInfo` class.
- **DTS.Common.Interface**: Contains `TextAttribute`, `ImageAttribute` base classes.
- **DTS.Viewer.ChartOptions.Model**: Contains `IChartOptionsModel`, `ChartOptionsModel`.
- **Local Types**: `ChartOptionsView`, `ChartOptionsViewModel`, `IChartOptionsView`, `IChartOptionsViewModel` (referenced but not shown in this file).
### What Depends On This Module:
- **DTS Viewer Main Application**: Uses the assembly-level attributes to discover and display this module in the UI; resolves the registered views/view-models via the container.
---
## 5. Gotchas
1. **Comment Inaccuracy**: The comment on line 37 states "Register View & View-Model with Unity dependency injection container as a singleton." However, `_unityContainer.RegisterType<TFrom, TTo>()` without an explicit `ContainerControlledLifetimeManager` registers types as **transient**, not singleton. The comment does not match the actual behavior.
2. **Unused Constructor Parameters**: Both attribute classes have constructors accepting a `string s` parameter that is never used. This appears to be a requirement of the attribute system (attributes require parameterless constructors or constructors with constant values), but the parameter serves no functional purpose.
3. **Empty `OnInitialized` Method**: The `OnInitialized` method is explicitly implemented but empty. It is unclear whether this is intentional (no initialization logic needed) or represents incomplete implementation.
4. **Dual Initialization Pattern**: The `Initialize()` method is called from within `RegisterTypes()`. This is unconventional—typically `RegisterTypes` handles registration directly. The separate `Initialize()` method may be a legacy pattern or intended for reuse elsewhere.

View File

@@ -0,0 +1,120 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/Model/ChartOptionsModel.cs
generated_at: "2026-04-16T13:57:20.201859+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "a2e58408ee52b3f9"
---
# Documentation: ChartOptionsModel.cs
## 1. Purpose
`ChartOptionsModel` is a state management class for chart configuration options within the DTS Viewer application. It serves as the data model backing chart visualization controls, managing unit types (EU, mV, V, PSD, FFT), time units, axis scaling modes, filter selections, cursor behavior, and zoom/pan state. The class implements `INotifyPropertyChanged` via `BasePropertyChanged` to support MVVM data binding and coordinates with a parent `IChartOptionsViewModel` to publish configuration changes.
---
## 2. Public Interface
### Properties
| Property | Type | Access | Description |
|----------|------|--------|-------------|
| `DisplayingVolts` | `bool` | get/set | Controls whether voltage displays as "V" (true) or "mV" (false). Raises `OnPropertyChanged` for `"MVOrV"` and `"UnitTypeDescription"` when changed. |
| `MVOrV` | `string` | get | Returns `"V"` if `DisplayingVolts` is true, otherwise `"mV"`. |
| `IsDigitalChannel` | `bool` | get/set | Indicates whether the current channel is digital. |
| `SupportsADC` | `bool` | get/set | Indicates ADC support for the current context. |
| `SupportsMV` | `bool` | get/set | Indicates mV unit support. |
| `UnitType` | `ChartUnitTypeEnum` | get/set | The current unit type (EU, mV, PSD, FFT, etc.). Changing this sets `ReadData = true` and auto-adjusts `Filter`. |
| `UnitTypeDescription` | `string` | get | Returns the display string for `UnitType`. Returns `"V"` or `"mV"` when `UnitType == ChartUnitTypeEnum.mV`. |
| `TimeUnitType` | `TimeUnitTypeEnum` | get/set | Time axis unit. Defaults to `TimeUnitTypeEnum.MS`. Changing sets `ReadData = true`. |
| `TimeUnitTypeDescription` | `string` | get/set | String representation of `TimeUnitType`. |
| `SelectedFilter` | `IFilterClass` | get/set | Currently selected filter class. Changing sets `ReadData = true`. |
| `MinFixedY` | `double` | get/set | Minimum Y-axis value for fixed scaling. |
| `MaxFixedY` | `double` | get/set | Maximum Y-axis value for fixed scaling. |
| `MinFixedT` | `double` | get/set | Minimum T (time) axis value for fixed scaling. |
| `MaxFixedT` | `double` | get/set | Maximum T (time) axis value for fixed scaling. |
| `FullScaleValues` | `List<double>` | get/set | Returns `_euValues` if `UnitType` is `EU` or `PSD`, otherwise `_fullScaleValues`. |
| `SelectedFullScaleValue` | `double` | get/set | Currently selected full-scale value. Defaults to `100`. |
| `LockedT` | `bool` | get/set | Whether the time axis is locked. |
| `LockedY` | `bool` | get/set | Whether the Y-axis is locked. |
| `ShowCursor` | `bool` | get/set | Cursor visibility. Setter calls `Parent?.ShowCusor(value)`. |
| `CurrentCursorValues` | `string` | get/set | Current cursor values display string. |
| `YRange` | `YRangeScaleEnum` | get/set | Y-axis range mode. Setting to `Fixed` automatically sets `LockedY = true`. |
| `Filter` | `FilterOptionEnum` | get/set | Filter option enum. Changing sets `ReadData = true`. |
| `Parent` | `IChartOptionsViewModel` | get/set | Parent view model reference. |
| `CanPublishChanges` | `bool` | get/set | Controls whether property changes trigger `Parent.PublishChanges()`. Defaults to `true`. |
| `IsCursorsAvailable` | `bool` | get/set | Whether cursors are available for the current context. |
| `T0Cursor` | `bool` | get/set | T0 cursor flag. |
| `MinMaxCursors` | `bool` | get/set | Min/Max cursors flag. |
| `ReadData` | `bool` | get/set | Flag indicating data should be re-read. |
| `IsSaved` | `bool` | get | Saved status (setter not visible in source). |
| `DecimateData` | `bool` | get/set | Getter returns `false` if `UnitType` is `PSD` or `FFT`, otherwise returns backing field value. |
| `WidthPoints` | `long` | get/set | Width points for decimation. |
### Commands
| Command | Type | Description |
|---------|------|-------------|
| `ResetZoomCommand` | `DelegateCommand` | Executes `ResetZoomMethod()`, which delegates to `Parent.ResetZoomMethod()`. |
| `ResetTCommand` | `DelegateCommand` | Executes `ResetTMethod()`, which delegates to `Parent.ResetTMethod()`. |
| `SaveToPDFCommand` | `DelegateCommand` | Executes `SaveToPDFMethod()`, which delegates to `Parent.SaveToPDFMethod()`. |
### Methods
| Method | Signature | Description |
|--------|-----------|-------------|
| `ChartOptionsModel` | `public ChartOptionsModel()` | Empty constructor. |
| `SetSelectedFilterToUnfilteredNoRead` | `public void SetSelectedFilterToUnfilteredNoRead()` | Sets `SelectedFilter` to unfiltered without setting `ReadData = true`. |
| `OnPropertyChanged` | `public void OnPropertyChanged(string propertyName)` | Raises `PropertyChanged` event and conditionally calls `Parent?.PublishChanges()`. |
### Events
| Event | Type | Description |
|-------|------|-------------|
| `PropertyChanged` | `PropertyChangedEventHandler` | Standard INotifyPropertyChanged event. |
---
## 3. Invariants
1. **UnitType → Filter coupling**: When `UnitType` is set to anything other than `EU` or `PSD`, `Filter` is automatically set to `FilterOptionEnum.Unfiltered`. When set to `EU` or `PSD`, `Filter` is set to `FilterOptionEnum.TestSetupDefault`.
2. **YRange → LockedY coupling**: Setting `YRange` to `YRangeScaleEnum.Fixed` automatically sets `LockedY = true`.
3. **DecimateData PSD/FFT exclusion**: `DecimateData` getter always returns `false` when `UnitType` is `ChartUnitTypeEnum.PSD` or `ChartUnitTypeEnum.FFT`, regardless of the backing field value.
4. **FullScaleValues selection**: The property returns `_euValues` (5000, 2500, 1000, 500, 100, 50, 10, 5) for `EU` or `PSD` unit types, and `_fullScaleValues` (200, 100, 50, 20, 10, 5, 1, 0.1) otherwise.
5. **ReadData side effects**: Setting `UnitType`, `TimeUnitType`, `SelectedFilter`, or `Filter` automatically sets `ReadData = true`.
---
## 4. Dependencies
### This module depends on:
- `DTS.Common` — Common utilities
- `DTS.Common.Classes.Sensors``FilterClass` implementation
- `DTS.Common.Enums.Viewer``ChartUnitTypeEnum`, `TimeUnitTypeEnum`, `FilterOptionEnum`, `YRangeScaleEnum`
- `DTS.Common.Interface``IChartOptionsModel` interface
- `DTS.Common.Interface.Sensors.SoftwareFilters``IFilterClass` interface
- `Prism.Commands``DelegateCommand` for MVVM commands
- `Common.Base.BasePropertyChanged` — Base class providing `SetProperty` method for INotifyPropertyChanged implementation
### What depends on this module:
- `IChartOptionsViewModel` implementations (referenced as `Parent` property)
---
## 5. Gotchas
1. **Typo in method call**: In `ShowCursor` setter, the code calls `Parent?.ShowCusor(_showCursor)` — note the misspelling "Cusor" instead of "Cursor". This may cause confusion when searching for the method definition.
2. **Conditional PublishChanges suppression**: The `OnPropertyChanged` method explicitly skips calling `Parent?.PublishChanges()` for specific property names: `"CanPublishChanges"`, `"Parent"`, `"ReadData"`, `"UnitTypeDescription"`, `"ShowCursor"`, `"LockedT"`, `"LockedY"`, `"MVOrV"`, `"DisplayingVolts"`, `"DecimateData"`, `"WidthPoints"`. This is not documented elsewhere and could lead to unexpected behavior.
3. **IsSaved property has no visible implementation**: The property has only a getter with no backing field or setter visible in the source. Its behavior is unclear from this file alone.
4. **SetSelectedFilterToUnfilteredNoRead bypasses normal flow**: This method directly sets the backing field `_selectedFilter` and sets `ReadData = false`, bypassing the normal property setter which would set `ReadData = true`.
5. **Inconsistent property change patterns**: Some properties use `SetProperty(ref _field, value, "PropertyName")` while others manually check equality and call `OnPropertyChanged`. This inconsistency may indicate incremental development over time.

View File

@@ -0,0 +1,44 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:56:36.683530+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "fddf8c3b00b320fd"
---
# Documentation for AssemblyInfo.cs
## 1. Purpose
This source file provides assembly-level metadata configuration for the `DTS.Viewer.ChartOptions` module. It exists to embed standard identifying information—such as title, version, and copyright—into the compiled assembly manifest. Its role is strictly limited to build-time configuration; it contains no executable application logic.
## 2. Public Interface
This file does not expose any public classes, methods, or functions. It applies the following assembly-level attributes:
* **`AssemblyTitle`**: Set to `"DTS.Viewer.DTS.Viewer.ChartOptions"`.
* **`AssemblyDescription`**: Empty.
* **`AssemblyConfiguration`**: Empty.
* **`AssemblyCompany`**: Empty.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.DTS.Viewer.ChartOptions"`.
* **`AssemblyCopyright`**: Set to `"Copyright © 2017"`.
* **`AssemblyTrademark`**: Empty.
* **`AssemblyCulture`**: Empty.
* **`ComVisible`**: Set to `false`. Prevents types within this assembly from being visible to COM components by default.
* **`Guid`**: Set to `"9f161f2a-4fcd-438e-9768-ba96ba104d6c"`. Serves as the ID for the type library if the assembly is 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 marked with `ComVisible(false)`. Therefore, all types within this assembly are invisible to COM by default unless a specific type is marked otherwise.
* **Versioning**: Both the assembly version and file version are fixed at `1.0.0.0`. Automatic versioning (e.g., using wildcards) is currently disabled/commented out.
## 4. Dependencies
* **Internal Dependencies**:
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* **External Consumers**: The compiled `DTS.Viewer.ChartOptions` assembly depends on this file for its manifest metadata. The build system consumes this file during compilation.
## 5. Gotchas
* **Naming Redundancy**: The `AssemblyTitle` and `AssemblyProduct` attributes are set to `"DTS.Viewer.DTS.Viewer.ChartOptions"`. This appears to duplicate the root namespace (`DTS.Viewer`) within the name, which may be a project naming convention or a configuration oversight.
* **Legacy Format**: This file uses the older .NET Framework style of `AssemblyInfo.cs`. In modern .NET Core/.NET 5+ projects (SDK-style projects), this metadata is typically defined in the project file (`.csproj`), though this file is still supported.

View File

@@ -0,0 +1,84 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:56:16.461808+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "8d340ea94a701586"
---
# Documentation: DTS.Viewer.ChartOptions Resources
## 1. Purpose
This module provides localization infrastructure for the `DTS.Viewer.ChartOptions` namespace. It consists of a strongly-typed resource accessor class (`StringResources`) generated from a `.resx` file, and a XAML markup extension (`TranslateExtension`) that allows UI elements to bind directly to localized strings. This separates user-facing string management from application logic, supporting multi-language scenarios.
## 2. Public Interface
### `TranslateExtension` (Class)
**Namespace:** `DTS.Viewer.ChartOptions`
**Inheritance:** `System.Windows.Markup.MarkupExtension`
This class enables XAML binding to localized resources.
* **Constructor**
* `public TranslateExtension(string key)`: Initializes the extension with the resource key to look up.
* **Methods**
* `public override object ProvideValue(IServiceProvider serviceProvider)`: Resolves the `_key` provided in the constructor to a localized string.
* Returns the localized string if found.
* Returns `#stringnotfound#` if the key is null or empty.
* Returns `#stringnotfound# [key]` if the lookup fails for a specific key.
### `StringResources` (Class)
**Namespace:** `DTS.Viewer.ChartOptions.Resources`
**Access Modifier:** `internal`
A strongly-typed resource class auto-generated by Visual Studio. It provides static properties to access culture-specific string values.
* **Properties**
* `internal static global::System.Resources.ResourceManager ResourceManager`: Gets the cached `ResourceManager` instance for this assembly.
* `internal static global::System.Globalization.CultureInfo Culture`: Gets or sets the current UI culture used for resource lookups.
* **Resource String Properties (Static, Read-Only)**
The following properties return localized strings corresponding to specific UI elements:
* `ChartUnitType`
* `FilterOptions_Title`
* `LockT`
* `MaxT`
* `MaxY`
* `MinT`
* `MinY`
* `Range`
* `ResetAll`
* `ResetT`
* `SaveChart`
* `SaveToPDF`
* `TimeUnitType`
## 3. Invariants
1. **Return Type Guarantee:** The `TranslateExtension` class is decorated with `[MarkupExtensionReturnType(typeof(string))]`, guaranteeing that `ProvideValue` returns a `string` (boxed as `object`).
2. **Non-Null Return:** `TranslateExtension.ProvideValue` will never return `null`. It guarantees a return value even if the key is missing or invalid (returning a fallback error string).
3. **Resource Manager Singleton:** `StringResources.ResourceManager` uses a lazy-initialization pattern; it creates the `ResourceManager` instance only once and caches it in the private static field `resourceMan`.
4. **Immutability of Key:** Once `TranslateExtension` is constructed, the `_key` field is `readonly` and cannot be changed.
## 4. Dependencies
**Internal Dependencies:**
* `TranslateExtension` depends entirely on `StringResources.ResourceManager` to perform the actual string lookup.
**External Dependencies:**
* `System.Windows.Markup`: Required for `MarkupExtension` and `IServiceProvider` (implies this is a WPF module).
* `System.Resources`: Required for `ResourceManager`.
* `System.Globalization`: Required for `CultureInfo`.
**Downstream Dependencies:**
* XAML files within the `DTS.Viewer.ChartOptions` module (or other modules referencing this namespace) depend on `TranslateExtension` to display localized text (e.g., usage likely looks like `{local:Translate KeyName}`).
## 5. Gotchas
1. **Silent Failure Behavior:** `TranslateExtension` does not throw exceptions for missing keys. Instead, it returns the literal string `#stringnotfound#` (for null/empty keys) or `#stringnotfound# [key]` (for missing keys). This visual indicator might appear in the UI if resources are misconfigured, rather than causing a compile-time or runtime crash.
2. **Auto-Generated Code:** `StringResources` is marked with `GeneratedCodeAttribute`. Manual edits to this file will be overwritten if the resource tooling regenerates it. The actual string values reside in an external `.resx` file (likely `StringResources.resx`) which is not visible in the provided source but is implied by the designer file.
3. **Internal Visibility:** The `StringResources` class is `internal`. It cannot be accessed directly from outside the `DTS.Viewer.ChartOptions` assembly. However, `TranslateExtension` is `public`, allowing external assemblies to use the XAML extension if they reference this assembly.
4. **Case Sensitivity:** The `ResourceManager.GetString` method called by `TranslateExtension` is typically case-sensitive regarding the resource key (depending on the underlying resource set implementation), though the constant `_key` is passed exactly as provided to the constructor.

View File

@@ -0,0 +1,66 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/View/ChartOptionsView.xaml.cs
generated_at: "2026-04-16T13:56:57.437477+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "2fdf05f68ae69d8d"
---
# Documentation: ChartOptionsView
## 1. Purpose
`ChartOptionsView` is a WPF view component that provides user interface logic for configuring chart display options. It implements the `IChartOptionsView` interface, serving as the visual layer for chart-related settings within the DTS Viewer application. The view exposes available filter class options that can be applied to sensor data visualization.
---
## 2. Public Interface
### `ChartOptionsView()` (Constructor)
**Signature:** `public ChartOptionsView()`
Initializes a new instance of the `ChartOptionsView` class. Calls `InitializeComponent()` to load the associated XAML layout.
---
### `AvailableCFC` (Property)
**Signature:** `public List<IFilterClass> AvailableCFC { get; }`
A read-only property that returns the list of available filter classes (CFC = Constant Fraction Classes, per FB 13120).
**Behavior:** Each access instantiates a new `AnalogSettingDefaults` object and returns its `FilterOptions` property.
**Returns:** `List<IFilterClass>` containing the available filter options.
---
## 3. Invariants
- The `AvailableCFC` property getter always creates a **new instance** of `AnalogSettingDefaults` on every access; it does not cache or reuse the object.
- The view always implements `IChartOptionsView` as its contract with the rest of the system.
- The XAML component (referenced via `InitializeComponent()`) is expected to be present and properly compiled as part of the partial class definition.
---
## 4. Dependencies
### This module depends on:
| Namespace | Type Used |
|-----------|-----------|
| `DTS.Common.Interface` | `IChartOptionsView` |
| `DTS.Common.Interface.Sensors.SoftwareFilters` | `IFilterClass` |
| `DTS.SensorDB` | `AnalogSettingDefaults` |
### What depends on this module:
**Unclear from source alone.** The `IChartOptionsView` interface suggests a presenter, view model, or controller consumes this view, but no direct consumers are visible in this file.
---
## 5. Gotchas
1. **Instance creation on every property access:** The `AvailableCFC` property instantiates a new `AnalogSettingDefaults` object on every call. If this property is data-bound in XAML and accessed frequently (e.g., by a UI update loop), it could create unnecessary object allocations and GC pressure. Consider whether caching would be appropriate.
2. **FB 13120 reference:** The XML comment references "FB 13120" (likely a feature/bug tracking identifier). The business context for why this property exists or what specific requirement it addresses is not clear from source alone.
3. **Partial class definition:** This is a partial class. The XAML file (`ChartOptionsView.xaml`) defines additional structure (base class, visual elements) that is not visible here. The actual base class (likely `UserControl` or similar) is defined in the XAML.

View File

@@ -0,0 +1,124 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ChartOptions/ViewModel/ChartOptionsViewModel.cs
generated_at: "2026-04-16T13:55:59.501828+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "7f2f2e90f6f17587"
---
# Documentation: ChartOptionsViewModel
## 1. Purpose
`ChartOptionsViewModel` is a Prism-based ViewModel that manages chart configuration options for the DTS Viewer application. It serves as an intermediary between chart views and the event system, handling axis range settings, unit type selection (EU, mV, ADC), cursor visibility controls, and publishing chart option changes to other application components. The module supports multiple parent contexts including `IViewerMainViewModel` and `IPSDReportMainViewModel`, with different initialization behaviors for each.
---
## 2. Public Interface
### Constructor
```csharp
public ChartOptionsViewModel(
IChartOptionsView view,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the ViewModel, sets up interaction requests, and subscribes to `ChartAxisChangedEvent`.
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `Parent` | `IBaseViewModel` | Reference to the parent ViewModel. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism interaction request for confirmations. |
| `View` | `IBaseView` | Associated view instance. |
| `Model` | `IChartOptionsModel` | The chart options model; setter triggers `OnPropertyChanged("Model")`. |
| `ContextSearchRegion` | `object` | Region context for search functionality. |
| `IsMenuIncluded` | `bool` | Hides base member; menu inclusion flag. |
| `IsNavigationIncluded` | `bool` | Hides base member; navigation inclusion flag. |
| `IsBusy` | `bool` | Hides base member; busy state indicator. |
| `IsDirty` | `bool` | Hides base member; dirty state (get-only). |
| `ChartOptionsVisability` | `bool` | Controls visibility of chart options UI; defaults to `false`. |
| `ClearMarkersCommand` | `DelegateCommand` | Command that invokes `ClearMarkersMethod()`. |
### Methods
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `override void Initialize()` | Empty override; no implementation. |
| `Initialize` | `override void Initialize(object parameter)` | Main initialization accepting `IViewerMainViewModel` or `Tuple<IBaseViewModel, string>` containing `IPSDReportMainViewModel`. Sets up model, subscriptions, and configures based on parameter type. |
| `ShowMinMaxCursor` | `void ShowMinMaxCursor(bool value)` | Publishes `CursorShowMinMaxChangedEvent` with the boolean value. |
| `ResetZoomMethod` | `void ResetZoomMethod()` | Sets `Model.YRange` to `AutoRange` and publishes `ResetZoomChangedEvent(true)`. |
| `ResetTMethod` | `void ResetTMethod()` | Publishes `ResetZoomChangedEvent(false)`. |
| `SaveToPDFMethod` | `void SaveToPDFMethod()` | Publishes `SaveToPDFRequestedEvent` with the `Directory` path. |
| `PublishChanges` | `void PublishChanges()` | Publishes `ChartOptionsChangedEvent` with `ChartOptionsChangedEventArg` containing `ParentVM`, `Model`, and `ChartType`. |
| `ShowCusor` | `void ShowCusor(bool value)` | Publishes `CursorShowChangedEvent` with the boolean value. |
| `OnPropertyChanged` | `new void OnPropertyChanged(string propertyName)` | Raises `PropertyChanged` event. |
---
## 3. Invariants
1. **Model Resolution**: `Model` must be resolved via `_unityContainer.Resolve<IChartOptionsModel>()` before use; it is not resolved in the constructor but in `Initialize(object parameter)`.
2. **Parent Matching for Events**: Event handlers (`OnChartAxisChangedEvent`, `OnGraphSelectedChannelsChanged`) check `args?.ParentVM != Parent` and return early if the event is not intended for this instance.
3. **Publish Control**: `Model.CanPublishChanges` must be `true` for changes to propagate via `PublishChanges()`. It is set to `false` during batch configuration updates.
4. **Unit Type Fallback**: If channels do not support ADC or mV (determined by `AllChannelsSupportADC` / `AllChannelsSupportmV`), the `UnitType` falls back to `ChartUnitTypeEnum.EU`.
5. **ADC/mV Support Detection**: Both `AllChannelsSupportADC` and `AllChannelsSupportmV` return `false` if any channel's parent module has a TSR AIR serial number (checked via `HardwareConstants.IsTSRAIRSerialNumber`).
6. **Graph Chart Type Constraints**: When `chartType == "Graph"`, the model is configured with:
- `UnitType = ChartUnitTypeEnum.PSD`
- `YRange = YRangeScaleEnum.Fixed`
- `MaxFixedY = 1`
- `MinFixedY = 1e-12` (non-zero for log scale)
- `DecimateData = false`
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base` - `BaseViewModel<IChartOptionsViewModel>`
- `DTS.Common.Enums.Viewer` - `ChartUnitTypeEnum`, `YRangeScaleEnum`, `FilterOptionEnum`
- `DTS.Common.Events` - `ChartAxisChangedEvent`, `CursorsAlailableChangedEvent`, `GraphSelectedChannelsNotification`, `CursorShowMinMaxChangedEvent`, `ResetZoomChangedEvent`, `SaveToPDFRequestedEvent`, `ChartOptionsChangedEvent`, `CursorShowChangedEvent`, `CursorsClearChangedEvent`
- `DTS.Common.Interface` - `IChartOptionsViewModel`, `IChartOptionsModel`, `IChartOptionsView`, `IBaseViewModel`, `IBaseView`, `IViewerMainViewModel`, `IPSDReportMainViewModel`, `ITestChannel`
- `DTS.Common.Interactivity` - Interaction requests
- `DTS.Common.Enums.Hardware` - `HardwareConstants.IsTSRAIRSerialNumber()`
- `Prism.Events` - `IEventAggregator`
- `Prism.Regions` - `IRegionManager`
- `Prism.Commands` - `DelegateCommand`
- `Unity` - `IUnityContainer`
### What Depends On This Module:
- Not explicitly shown in source; inferred consumers include:
- `IChartOptionsView` implementations
- `IViewerMainViewModel` implementations
- `IPSDReportMainViewModel` implementations
---
## 5. Gotchas
1. **Misleading XML Documentation**: The constructor's XML comment references `TestSummaryViewModel` instead of `ChartOptionsViewModel` — appears to be copy-paste tech debt.
2. **`new` Keyword Hiding**: Multiple members (`IsMenuIncluded`, `IsNavigationIncluded`, `IsBusy`, `IsDirty`, `ConfirmationRequest`, `Model`, `PropertyChanged`, `OnPropertyChanged`) use the `new` keyword to hide base class members. This can cause unexpected behavior when casting to base types.
3. **Typo in Property Name**: `ChartOptionsVisability` should be `ChartOptionsVisibility`.
4. **Typo in Method Name**: `ShowCusor` should be `ShowCursor`.
5. **Typo in Event Handler**: `OnCursorsAlailableChanged` and `CursorsAlailableChangedEvent` misspell "Available" as "Alailable".
6. **Identical ADC/mV Logic**: `AllChannelsSupportADC` and `AllChannelsSupportmV` have identical implementations. The comment in `AllChannelsSupportADC` suggests this may be placeholder logic based on serial numbers, with future sophistication planned.
7. **Unused/Private Fields**: Several ReSharper suppressions (`UnassignedGetOnlyAutoProperty`, `NotAccessedField.Local`, `UnusedAutoPropertyAccessor.Local`) suggest dead code or incomplete implementations.
8. **Commented-Out Constructor Code**: Lines resolving and assigning `Model` in the constructor are commented out, suggesting initialization was moved to `Initialize(object parameter)`.
9. **Directory Property Purpose Unclear**: The `Directory` property is set from the first selected channel's `BinaryFilePath` and used only in `SaveToPDFMethod()`. The relationship between chart options and this directory is not documented.

View File

@@ -0,0 +1,90 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/FilterModule.cs
generated_at: "2026-04-16T13:44:23.497575+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ba34bc552f65e535"
---
# Documentation: DTS.Viewer.Filter.FilterModule
## 1. Purpose
This module serves as the entry point for the "Filter" component within the larger DTS Viewer application. It is a Prism Module (`FilterModule`) responsible for registering the Filter's View and ViewModel with the Unity dependency injection container. Additionally, it defines assembly-level attributes (`FilterPropertiesNameAttribute`, `FilterPropertiesImageAttribute`) that expose metadata—such as the module name, region, and display image—to the main application shell, likely for dynamic UI generation or module listing.
## 2. Public Interface
### Classes
#### `FilterModule`
Implements `Prism.Modularity.IModule`. It handles the module initialization and dependency injection registration.
* **`FilterModule(IUnityContainer unityContainer)`**
* Constructor that accepts an `IUnityContainer` instance via dependency injection and stores it in a private readonly field.
* **`void RegisterTypes(IContainerRegistry containerRegistry)`**
* Implements `IModule.RegisterTypes`. It invokes the private `Initialize()` method to perform DI registration.
* **`void OnInitialized(IContainerProvider containerProvider)`**
* Implements `IModule.OnInitialized`. Currently contains no implementation logic.
#### `FilterPropertiesNameAttribute`
Inherits from `DTS.Common.Interface.TextAttribute`. Provides the assembly name metadata.
* **`FilterPropertiesNameAttribute()`**
* Default constructor. Initializes `_assemblyName` using `AssemblyNames.Filter.ToString()`.
* **`string AssemblyName` (Property)**
* Overrides the base property. Returns the stored assembly name string.
* **`Type GetAttributeType()`**
* Returns `typeof(TextAttribute)`.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property value.
#### `FilterPropertiesImageAttribute`
Inherits from `DTS.Common.Interface.ImageAttribute`. Provides image, region, and grouping metadata for the assembly.
* **`FilterPropertiesImageAttribute()`**
* Default constructor. Initializes the `_img` field using `AssemblyInfo.GetImage(AssemblyNames.Filter.ToString())`.
* **`BitmapImage AssemblyImage` (Property)**
* Overrides the base property. The getter re-fetches the image using `AssemblyInfo.GetImage` before returning it.
* **`string AssemblyName` (Property)**
* Returns `AssemblyNames.Filter.ToString()`.
* **`string AssemblyGroup` (Property)**
* Returns `eAssemblyGroups.Viewer.ToString()`.
* **`eAssemblyRegion AssemblyRegion` (Property)**
* Returns `eAssemblyRegion.FilterRegion`.
* **`BitmapImage GetAssemblyImage()`**
* Returns the `AssemblyImage` property.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property.
* **`eAssemblyRegion GetAssemblyRegion()`**
* Returns the `AssemblyRegion` property.
* **`string GetAssemblyGroup()`**
* Returns the `AssemblyGroup` property.
* **`Type GetAttributeType()`**
* Returns `typeof(ImageAttribute)`.
## 3. Invariants
* **Module Name:** The module is identified by the string `"FilterProperties"` (defined in the `[Module]` attribute).
* **Attribute Uniqueness:** Both `FilterPropertiesNameAttribute` and `FilterPropertiesImageAttribute` are decorated with `AttributeUsage(..., AllowMultiple = false)`, ensuring only one instance of each exists per assembly.
* **Registration Mapping:** The `Initialize` method strictly maps `IFilterView` to `FilterView` and `IFilterViewModel` to `FilterViewModel`.
* **Region Assignment:** The module is hardcoded to belong to the `eAssemblyRegion.FilterRegion` region.
* **Group Assignment:** The module is hardcoded to belong to the `eAssemblyGroups.Viewer` group.
## 4. Dependencies
### Internal Dependencies (Inferred)
* **DTS.Common:** Uses `AssemblyNames` enum, `AssemblyInfo` static class, `eAssemblyRegion` enum, and `eAssemblyGroups` enum.
* **DTS.Common.Interface:** Uses `TextAttribute`, `ImageAttribute`, `IFilterView`, and `IFilterViewModel` interfaces.
* **DTS.Viewer.Filter (Local):** References local concrete types `FilterView` and `FilterViewModel`.
### External Dependencies
* **Prism.Ioc & Prism.Modularity:** For `IModule`, `IContainerProvider`, and `IContainerRegistry`.
* **Unity:** For `IUnityContainer` (Microsoft.Practices.Unity or similar).
* **System.Windows.Media.Imaging:** For `BitmapImage`.
## 5. Gotchas
* **Comment/Code Mismatch (Singleton vs. Transient):** The comment in `Initialize()` states: *"Register View & View-Model ... as a singleton."* However, the code uses `_unityContainer.RegisterType<...>()`. In Unity, `RegisterType` registers a transient mapping (new instance every time) by default. To register as a singleton, `ContainerControlledLifetimeManager` should be used. The code does not match the comment.
* **Mixed Container Abstractions:** The class receives an `IUnityContainer` in the constructor but implements `RegisterTypes(IContainerRegistry containerRegistry)` from Prism. It ignores the `containerRegistry` parameter and instead calls `Initialize()` which uses the stored `_unityContainer`. This bypasses Prism's container abstraction, making the module tightly coupled to Unity and potentially ignoring configuration applied via the `IContainerRegistry` interface.
* **Side Effects in Property Getters:** In `FilterPropertiesImageAttribute`, the getter for `AssemblyImage` modifies the private field `_img` (`_img = ...; return _img;`). This is a side effect in a property getter, which is generally considered poor practice and could lead to unexpected behavior if the property is accessed frequently.
* **Unused Parameter:** The constructor of `FilterPropertiesImageAttribute(string s)` accepts a string parameter `s` but never uses it. The same applies to `FilterPropertiesNameAttribute`.

View File

@@ -0,0 +1,39 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:53:34.309511+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "84c02c8aaa174ca5"
---
# Documentation: DTS.Viewer.Filter Properties
## 1. Purpose
This file provides assembly-level configuration and metadata for the `DTS.Viewer.Filter` module (compiled as a .NET assembly). It defines the assembly's identity, version information, and COM visibility settings. Its role is to embed standard manifest information into the compiled DLL so it can be correctly identified and versioned by the .NET runtime and the operating system.
## 2. Public Interface
This file does not contain executable classes or methods. It exposes configuration via .NET assembly attributes.
* **`AssemblyTitle`**: Set to the string `"DTS.Viewer.Search"`.
* **`AssemblyProduct`**: Set to the string `"DTS.Viewer.Search"`.
* **`AssemblyVersion`**: Set to the string `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to the string `"1.0.0.0"`.
* **`ComVisible`**: Set to `false`.
* **`Guid`**: Set to `"e958450a-4e86-46bd-8b9a-65fcf8326423"`.
## 3. Invariants
* **COM Visibility:** Types within this assembly are not visible to COM components by default (`ComVisible(false)`).
* **Versioning:** The assembly version and file version are fixed at `1.0.0.0`.
* **Identity:** The assembly is identified by the GUID `e958450a-4e86-46bd-8b9a-65fcf8326423` if exposed to COM.
## 4. Dependencies
* **Internal Dependencies:**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* **External Dependents:** Other projects within the solution may reference this assembly, relying on the version number `1.0.0.0` for binding.
## 5. Gotchas
* **Naming Mismatch:** There is a significant discrepancy between the file path and the assembly metadata. The file is located in `DTS.Viewer.Filter/Properties/`, but the `AssemblyTitle` and `AssemblyProduct` attributes are explicitly set to `"DTS.Viewer.Search"`. This suggests the code was likely copied from the Search module and the attributes were not updated to match the Filter module's name. This may cause confusion in logs or assembly lists.
* **Missing Description:** The `AssemblyDescription` attribute is an empty string, providing no documentation on the module's specific functionality.

View File

@@ -0,0 +1,76 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:53:45.876362+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "6fd260c9e57c0fd4"
---
# Documentation: DTS.Viewer.Filter.Resources
## 1. Purpose
This module provides localization support for the `DTS.Viewer.Filter` namespace. It consists of a XAML markup extension (`TranslateExtension`) that allows UI elements to bind to localized strings dynamically, and a strongly-typed resource accessor class (`StringResources`) generated from a `.resx` file. The module bridges the gap between XAML markup and .NET resource management, ensuring that string resources are resolved at runtime based on the current culture.
## 2. Public Interface
### `TranslateExtension` (Class)
**Namespace:** `DTS.Viewer.Filter`
**Inheritance:** `System.Windows.Markup.MarkupExtension`
This is the primary public class used in XAML to retrieve localized strings.
* **Constructor: `TranslateExtension(string key)`**
* Initializes a new instance of the extension with the specified resource key.
* **Parameter `key`**: The name of the string resource to look up.
* **Method: `ProvideValue(IServiceProvider serviceProvider)`**
* **Return Type:** `object`
* **Behavior:** Looks up the string value associated with `_key` via `StringResources.ResourceManager`.
* Returns the localized string if found.
* Returns the constant `"#stringnotfound#"` if the input `_key` is null or empty.
* Returns `"#stringnotfound# " + _key` if the lookup key does not exist in the resource set (i.e., `GetString` returns null).
### `StringResources` (Class)
**Namespace:** `DTS.Viewer.Filter.Resources`
**Attribute:** `internal` (Not publicly accessible outside the assembly)
This is an auto-generated class providing strongly-typed access to string resources.
* **Property: `ResourceManager`**
* **Type:** `global::System.Resources.ResourceManager`
* **Accessibility:** `internal static`
* **Behavior:** Returns a cached instance of the resource manager for the resource bundle `"DTS.Viewer.Filter.Resources.StringResources"`.
* **Property: `Culture`**
* **Type:** `global::System.Globalization.CultureInfo`
* **Accessibility:** `internal static`
* **Behavior:** Gets or sets the current UI culture used for resource lookups. Overrides `CurrentUICulture` for this resource class.
* **Property: `Search`**
* **Type:** `string`
* **Accessibility:** `internal static`
* **Behavior:** Looks up a localized string corresponding to the key `"Search"`.
## 3. Invariants
* **Null Safety in Lookup:** `TranslateExtension.ProvideValue` will never return `null`. It guarantees a string return, either the valid resource or a specific error string.
* **Error Format:** If a resource key is missing, the returned string will always follow the format `"#stringnotfound# " + key`.
* **Empty Key Handling:** An empty or null key passed to `TranslateExtension` returns exactly `"#stringnotfound#"` (without a trailing space or key name).
* **Resource Manager Singleton:** `StringResources.ResourceManager` uses a lazy initialization pattern; once instantiated, the same instance is returned for all subsequent calls.
## 4. Dependencies
* **Internal Dependencies:**
* `TranslateExtension` depends entirely on `DTS.Viewer.Filter.Resources.StringResources` for data retrieval.
* **External Framework Dependencies:**
* `System.Windows.Markup`: Required for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute` (indicates this is likely a WPF or Xamarin application).
* `System.Resources`: Required for `ResourceManager`.
* `System.Globalization`: Required for `CultureInfo`.
## 5. Gotchas
* **Differentiated Error States:** The module handles missing keys differently than null/empty keys.
* `key = null` or `""` $\rightarrow$ returns `"#stringnotfound#"`
* `key = "MissingKey"` $\rightarrow$ returns `"#stringnotfound# MissingKey"`
* Developers parsing or validating these strings must account for the space and key suffix in the latter case.
* **Auto-Generated Code:** `StringResources.Designer.cs` is auto-generated (Runtime Version:4.0.30319.42000). Manual changes to this file will be overwritten. The underlying `.resx` file must be edited to persist changes.
* **Visibility Mismatch:** `TranslateExtension` is `public`, but `StringResources` is `internal`. This implies `TranslateExtension` is the intended public API for external consumers, while direct access to `StringResources` is restricted to within the assembly.

View File

@@ -0,0 +1,59 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/View/FilterView.xaml.cs
generated_at: "2026-04-16T13:53:49.176604+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "172c435d25b31364"
---
# Documentation: FilterView.xaml.cs
## 1. Purpose
This module provides the code-behind implementation for `FilterView`, a WPF user control representing a filter UI component within the DTS Viewer application. It serves as a view in the application's filter module, implementing the `IFilterView` interface to integrate with the broader system architecture. The actual UI layout and controls are defined in the associated XAML file (`FilterView.xaml`), while this file handles the view's initialization and any code-behind logic.
## 2. Public Interface
### `FilterView` Class
**Signature:**
```csharp
public partial class FilterView : IFilterView
```
**Description:** A WPF partial class representing a filter view component. Implements `IFilterView` from `DTS.Common.Interface`, indicating it conforms to a view contract expected by the system.
#### Constructor
**Signature:**
```csharp
public FilterView()
```
**Description:** Default constructor that initializes the XAML component by calling `InitializeComponent()`. This is the standard WPF pattern for loading and instantiating the XAML-defined UI elements.
## 3. Invariants
- The class must always implement `IFilterView` from `DTS.Common.Interface`.
- `InitializeComponent()` must be called exactly once during construction for the XAML-defined UI to be properly instantiated.
- As a partial class, there must exist a corresponding `FilterView.xaml` file that defines the UI structure.
## 4. Dependencies
### This module depends on:
- `DTS.Common.Interface.IFilterView` - Interface contract that this view implements
### External framework dependencies (inferred):
- WPF (Windows Presentation Foundation) - Required for `InitializeComponent()` and user control functionality
### What depends on this module:
- **Cannot be determined from source alone** - No consumers are visible in this file.
## 5. Gotchas
1. **Namespace suppression**: The file contains `// ReSharper disable CheckNamespace`, suggesting the namespace `DTS.Viewer.Filter` may not match the project's folder structure convention. This could indicate a historical refactoring or intentional namespace organization that differs from the physical file location.
2. **Minimal implementation**: The view contains no additional logic beyond initialization. Any filtering behavior, data binding, or interaction logic is either:
- Defined entirely in the XAML file
- Handled by a separate ViewModel (MVVM pattern)
- **Cannot be determined from source alone**

View File

@@ -0,0 +1,119 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Filter/ViewModel/FilterViewModel.cs
generated_at: "2026-04-16T13:53:02.291990+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "0bfa10177d1e439d"
---
# Documentation: FilterViewModel.cs
## 1. Purpose
`FilterViewModel` is a Prism-based MVVM view model that manages a filter/search text input component within the DTS Viewer application. It handles user input for filtering data, publishes `FilterParameterChangedEvent` notifications when filter criteria change, and manages placeholder text behavior (showing/hiding default "Search" text on focus events). The module serves as a reusable filter control that can be embedded in various views and communicates with parent view models via event aggregation.
---
## 2. Public Interface
### Constructor
```csharp
public FilterViewModel(IFilterView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the view model, sets up the view's DataContext, creates interaction requests, subscribes to `FilterParameterChangedEvent`, and initializes `_filterParam` to the default search text.
### Properties
| Property | Type | Access | Description |
|----------|------|--------|-------------|
| `View` | `IBaseView` | get/set | The associated view interface |
| `Parent` | `IBaseViewModel` | get/set | The parent view model, set during initialization |
| `NotificationRequest` | `InteractionRequest<Notification>` | get | Prism interaction request for notifications |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | get | Prism interaction request for confirmations |
| `Requester` | `IBaseViewModel` | get/set | Identifies the requester of filter operations |
| `IsMenuIncluded` | `bool` | get/set | Hides base member; purpose unclear from source |
| `IsNavigationIncluded` | `bool` | get/set | Hides base member; purpose unclear from source |
| `IsBusy` | `bool` | get/set | Hides base member; busy state indicator |
| `IsDirty` | `bool` | get | Hides base member; always returns default `false` |
| `ContextSearchRegion` | `object` | get/set | Purpose unclear from source |
| `SearchButtonVisability` | `bool` | get/set | Controls visibility of a search button (note: typo in name) |
| `FilterParam` | `string` | get/set | The current filter parameter value; setter publishes `FilterParameterChangedEvent` under certain conditions |
### Methods
```csharp
public override void Initialize(object parameter)
```
Sets `Parent` and `Requester` to the provided parameter (cast to `IBaseViewModel`).
```csharp
private new void OnPropertyChanged(string propertyName)
```
Raises the `PropertyChanged` event. Hides base member.
### Commands
| Command | Action Method | Behavior |
|---------|---------------|----------|
| `ClickedCommand` | `ClickedCommandAction()` | Empty implementation—no behavior |
| `GotFocusActionCommand` | `GotFocusAction()` | Clears `FilterParam` to empty string if it equals `FilterParamDefault` |
| `LostFocusActionCommand` | `LostFocusAction()` | Resets `FilterParam` to `FilterParamDefault` if it is null or empty |
### Events
```csharp
public new event PropertyChangedEventHandler PropertyChanged
```
Hides base member; raised by `OnPropertyChanged`.
---
## 3. Invariants
1. **FilterParamDefault**: The constant `Resources.StringResources.Search` defines the placeholder text displayed when no filter is active.
2. **Filter Event Suppression**: The `FilterParam` setter will **not** publish `FilterParameterChangedEvent` when:
- Current value equals `FilterParamDefault` AND new value is empty string, OR
- New value equals `FilterParamDefault`
3. **Requester Null Check**: In `OnFilterParameterChanged`, if `args.Requester` is not null, the method returns early without updating `_filterParam`. This is used to handle the "landing page revisit" scenario (per comment referencing issue 15641).
4. **Base Class Hiding**: Multiple members use the `new` keyword to hide base class implementations, which may affect polymorphic behavior.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base``BaseViewModel<T>`
- `DTS.Common.Events``FilterParameterChangedEvent`, `FilterParameterArgs`
- `DTS.Common.Interactivity``InteractionRequest<T>`, `Notification`, `Confirmation`
- `DTS.Common.Interface``IBaseView`, `IBaseViewModel`, `IFilterView`, `IFilterViewModel`
- `Prism.Commands``DelegateCommand`
- `Prism.Events``IEventAggregator`
- `Prism.Regions``IRegionManager`
- `Unity``IUnityContainer`
- `DTS.Viewer.Filter.Resources.StringResources``Search` constant
### What Depends On This Module:
**Not determinable from source alone.** The `IFilterViewModel` interface and `IFilterView` suggest consumption by a view layer and potentially other modules that publish `FilterParameterChangedEvent`.
---
## 5. Gotchas
1. **Typo in Property Name**: `SearchButtonVisability` is misspelled (should be "Visibility"). This typo is exposed in the public API and may propagate to XAML bindings.
2. **Member Hiding with `new` Keyword**: The properties `IsMenuIncluded`, `IsNavigationIncluded`, `IsBusy`, `IsDirty`, the `PropertyChanged` event, and `OnPropertyChanged` method all hide base class members. This breaks polymorphism—if the view model is accessed via a base class reference, the base members will be used instead of these implementations.
3. **IsDirty Always False**: The `IsDirty` property has only a getter with no implementation, meaning it always returns `false`. This may be unintended or incomplete.
4. **Empty Command Implementation**: `ClickedCommand` invokes `ClickedCommandAction()` which has an empty body. This may be dead code or a placeholder for future functionality.
5. **Duplicate Dependency Storage**: `_eventAggregator` and `_unityContainer` are stored as private auto-properties despite being passed to the base constructor. This creates redundant storage.
6. **Direct Field Assignment in Event Handler**: `OnFilterParameterChanged` assigns directly to the `_filterParam` backing field rather than the `FilterParam` property, bypassing the setter logic and preventing recursive event publication.
7. **ReSharper Suppressions**: The file includes 7 ReSharper suppression directives, suggesting known code quality issues that were silenced rather than addressed.

View File

@@ -0,0 +1,81 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/GraphModule.cs
generated_at: "2026-04-16T13:43:35.728588+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b6bfcd5e53808ea8"
---
# Documentation: DTS.Viewer.Graph Module
## 1. Purpose
This module serves as the Prism module definition for the `DTS.Viewer.Graph` component within the DTS Viewer application. Its primary role is to register Graph-related views and view models with the Unity dependency injection container during application startup. Additionally, it defines assembly-level attributes (`GraphNameAttribute`, `GraphImageAttribute`) that provide metadata—such as the assembly name, display image, and region assignment—used by the main application shell to identify and display the Graph module.
## 2. Public Interface
### Class: `GraphModule`
Implements `Prism.Modularity.IModule`. It is the entry point for the module's configuration.
* **`GraphModule(IUnityContainer unityContainer)`**
* Constructor that accepts an `IUnityContainer` instance via dependency injection and stores it in a readonly field.
* **`void RegisterTypes(IContainerRegistry containerRegistry)`**
* Implementation of the `IModule` interface. It invokes the `Initialize()` method to perform type registrations. Note that it ignores the passed `IContainerRegistry` and uses the injected `IUnityContainer` instead.
* **`void OnInitialized(IContainerProvider containerProvider)`**
* Implementation of the `IModule` interface. Currently contains no implementation logic.
* **`void Initialize()`**
* Registers types with the Unity container. It maps interfaces to concrete implementations for the following pairs:
* `IGraphView``GraphView`
* `IGraphViewModel``GraphViewModel`
* `ITestDataSeriesView``TestDataSeriesView`
* `ITestDataSeriesViewModel``TestDataSeriesViewModel`
### Class: `GraphNameAttribute`
Inherits from `DTS.Common.Interface.TextAttribute`. Applied at the assembly level to provide the module's name.
* **`GraphNameAttribute()`**
* Default constructor. Initializes the internal `_assemblyName` field using `AssemblyNames.Graph.ToString()`.
* **`string AssemblyName`** (Property)
* Returns the stored assembly name string.
* **`Type GetAttributeType()`**
* Returns `typeof(TextAttribute)`.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property value.
### Class: `GraphImageAttribute`
Inherits from `DTS.Common.Interface.ImageAttribute`. Applied at the assembly level to provide display metadata.
* **`BitmapImage AssemblyImage`** (Property)
* Gets the module's image by calling `AssemblyInfo.GetImage(AssemblyNames.Graph.ToString())`.
* **`string AssemblyName`** (Property)
* Returns `AssemblyNames.Graph.ToString()`.
* **`string AssemblyGroup`** (Property)
* Returns `eAssemblyGroups.Viewer.ToString()`.
* **`eAssemblyRegion AssemblyRegion`** (Property)
* Returns `eAssemblyRegion.GraphRegion`.
* **`BitmapImage GetAssemblyImage()`**, **`string GetAssemblyName()`**, **`string GetAssemblyGroup()`**, **`eAssemblyRegion GetAssemblyRegion()`**
* Accessor methods returning the values of their corresponding properties described above.
## 3. Invariants
* **Container Consistency:** The module relies strictly on `IUnityContainer` for registration, despite `RegisterTypes` providing a generic `IContainerRegistry`.
* **Metadata Constants:** The `AssemblyName` is always derived from the `AssemblyNames.Graph` enum value. The `AssemblyGroup` is always `eAssemblyGroups.Viewer`, and the `AssemblyRegion` is always `eAssemblyRegion.GraphRegion`.
* **Attribute Usage:** Both `GraphNameAttribute` and `GraphImageAttribute` are decorated with `AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)`, ensuring single-instance application at the assembly level.
## 4. Dependencies
### Internal Dependencies (Inferred)
* **`DTS.Common`**: Used for `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, and `AssemblyInfo`.
* **`DTS.Common.Interface`**: Defines `TextAttribute`, `ImageAttribute`, and the view/view model interfaces (`IGraphView`, `IGraphViewModel`, `ITestDataSeriesView`, `ITestDataSeriesViewModel`).
* **Local Types**: The module registers but does not define `GraphView`, `GraphViewModel`, `TestDataSeriesView`, and `TestDataSeriesViewModel`.
### External Dependencies
* **`Prism.Ioc`**: Provides `IContainerProvider`, `IContainerRegistry`.
* **`Prism.Modularity`**: Provides `IModule`, `ModuleAttribute`.
* **`Unity`**: Provides `IUnityContainer`.
* **`System.Windows.Media.Imaging`**: Provides `BitmapImage`.
## 5. Gotchas
* **Bypassing Prism Abstractions:** The `RegisterTypes` method receives an `IContainerRegistry` parameter (standard Prism abstraction) but completely ignores it. Instead, it calls `Initialize()`, which uses the constructor-injected `IUnityContainer`. This tightly couples the module to the Unity container, defeating the purpose of Prism's container-agnostic `IContainerRegistry` interface.
* **Dead Code:** The `Initialize` method contains commented-out registrations for `ITestDataView` and `ITestDataViewModel`. This suggests incomplete refactoring or deprecated features that have not been removed.
* **Unused Constructor Parameters:** The constructors for `GraphNameAttribute(string s)` and `GraphImageAttribute(string s)` accept a string parameter `s` that is never used. The default constructors call these overloaded constructors with `null`, and the logic inside them ignores the argument entirely.
* **Property Side-Effects:** In `GraphImageAttribute`, the getter for `AssemblyImage` performs logic (`_img = AssemblyInfo.GetImage...`) rather than simply returning a cached value. While likely harmless, this means the image fetching logic runs every time the property is accessed, rather than just once in the constructor.

View File

@@ -0,0 +1,187 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeries.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Model/TestDataSeriesModel.cs
generated_at: "2026-04-16T13:52:27.037806+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "1630e6f30be700ba"
---
# Documentation: DTS.Viewer.Graph Module - Test Data Series Models
## 1. Purpose
This module provides the data models for representing and transforming test channel data into graphable series within the DTS Viewer application. `TestDataSeries` serves as the primary data transfer object holding channel metadata, X/Y coordinate arrays, statistical calculations, and visualization properties. `TestDataSeriesModel` acts as a factory/processor that reads raw binary channel data, applies transformations (including FFT and PSD calculations), and populates `TestDataSeries` instances for display. The module supports three data modes: regular time-series, FFT (Fast Fourier Transform), and PSD (Power Spectral Density) with configurable windowing and filtering.
---
## 2. Public Interface
### TestDataSeries Class
**Namespace:** `DTS.Viewer.Graph.Model`
**Inherits:** `Common.Base.BasePropertyChanged`
**Implements:** `ITestDataSeries`
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `HIC` | `bool` | Indicates if Head Injury Criteria data is present. |
| `HICValue` | `string` | Formatted HIC value. |
| `T1Time`, `T2Time` | `string` | T1/T2 timestamp strings for HIC calculations. |
| `TestGroup` | `string` | Test group identifier. |
| `TestId` | `string` | Unique test identifier. |
| `TestSetupName` | `string` | Name of the test setup configuration. |
| `ChannelId` | `string` | Channel identifier. |
| `Xvalue` | `double[]` | X-axis data array (time or frequency). |
| `Yvalue` | `double[]` | Y-axis data array (amplitude, magnitude, or PSD). |
| `GraphColor` | `Brush` | WPF brush for graph rendering. Internally stored as `byte[]` for thread-safety. |
| `IsSaved` | `bool` | Get-only property indicating save state. |
| `HardwareChannel` | `string` | Hardware channel name. |
| `GroupName` | `string` | Channel group name. |
| `SWAAF` | `string` | Software anti-aliasing filter setting. |
| `Bridge` | `string` | Bridge type identifier. |
| `HWAAF` | `string` | Hardware anti-aliasing filter rate. |
| `SampleRate` | `string` | Sample rate in Hz. |
| `ISOCode`, `ISOChannelName` | `string` | ISO channel identification. |
| `UserCode`, `UserChannelName` | `string` | User-defined channel identification. |
| `ChannelName` | `string` | Display channel name. |
| `Description` | `string` | Channel description. |
| `SensorSN` | `string` | Sensor serial number. |
| `SensorSNDisplay` | `string` | Get-only; returns `"N/A"` if `SensorSN` is test-specific embedded, otherwise returns `SensorSN`. |
| `EngineeringUnits` | `string` | Engineering units string. |
| `Excitation` | `string` | Excitation voltage. |
| `Polarity` | `string` | Sensor polarity. |
| `MinY`, `MaxY`, `AvgY`, `StdDevY` | `string` | Statistical values formatted as strings, default to `Strings.Table_NA`. |
| `PeakMagnitude` | `double` | Peak magnitude of frequencies (valid only when `FFT` is true). |
| `PeakFrequency` | `double` | Frequency of highest magnitude (valid only when `FFT` is true). |
| `GRMS` | `double` | Root-mean-squared acceleration (calculated for PSD results). |
| `FFT` | `bool` | Indicates whether series contains FFT-transformed data. |
| `T0EUValue` | `string` | T0 value string. |
| `RecordingMode` | `string` | Recording mode description. |
#### Methods
```csharp
public void SetStatsFromYValues()
```
Calculates and sets `AvgY`, `StdDevY`, `MinY`, `MaxY` from internal `Yvalue` array. Uses `"G5"` format for string conversion.
```csharp
public void SetStatsFromYValues(double[] values)
```
Overload that calculates statistics from a provided `double[]` array. Handles null/empty arrays by setting all stats to `Table_NA`.
```csharp
public void SetStatsFromChannel(ITestChannel channel)
```
Sets statistics from pre-calculated values on an `ITestChannel` instance (properties: `MinY`, `MaxY`, `AveY`, `StdDevY`, `T0Value`).
---
### TestDataSeriesModel Class
**Namespace:** `DTS.Viewer.Graph`
**Implements:** `IBaseModel`
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `Parent` | `IGraphViewModel` | Parent view model reference. |
| `_eventAggregator` | `IEventAggregator` | Prism event aggregator for publishing progress events. |
| `ErrorMessage` | `string` | Error message with `PropertyChanged` notification. |
| `IsSaved` | `bool` | Get-only property. |
#### Methods
```csharp
public Task<ITestDataSeries> GetTestDataAsync(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Async wrapper returning `GetTestData()`. **Warning:** Lacks `await` operators and runs synchronously (per compiler warning CS1998).
```csharp
public Task<List<ITestDataSeries>> GetTestDataAsync(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Async wrapper for multiple channels. Includes envelope channel if `psdSettings.ShowEnvelope` is true.
```csharp
public List<ITestDataSeries> GetTestData(List<ITestChannel> channels, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Synchronously processes multiple channels. Throws `Exception` with context on `OutOfDataException` or other failures. Logs failures via `APILogger.Log()`.
```csharp
public ITestDataSeries GetTestData(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
Returns `AddTestChannelToChart()` result.
```csharp
public TestDataSeries AddTestChannelToChart(ITestChannel channel, IChartOptionsModel chartOptions, bool bVolts, IPSDReportSettingsModel psdSettings = null)
```
**Primary processing method.** Reads binary channel data via `Serialization.SliceRaw.File.Reader.ReadChannelsBinaryData()`, applies transformations based on `chartOptions.UnitType`:
- **FFT mode** (`ChartUnitTypeEnum.FFT` with null `psdSettings`): Sets `FFT=true`, populates `PeakFrequency`, `PeakMagnitude`.
- **Regular mode** (null `psdSettings`): Time-series data with optional HIC calculation.
- **PSD mode** (non-null `psdSettings`): Applies data trimming, windowing (Hanning, Hamming, Blackman, BlackmanHarris, FlatTop, Rectangle), optional low/high pass filtering via `Exocortex.DSP`, and Welch PSD transform via `FftSharp.Transform.PSD_Welch()`.
Returns `null` if `channel.ErrorMessage` is not empty.
---
## 3. Invariants
1. **Array Initialization**: `Xvalue` and `Yvalue` are never null; they default to `new double[0]`.
2. **GraphColor Thread-Safety**: `GraphColor` getter creates a new `SolidColorBrush` on each call. The underlying color is stored as a 4-byte array (`[A, R, G, B]`) to enable cross-thread access.
3. **FFT/PSD Filter Bypass**: When `chartOptions.UnitType` is `FFT` or `PSD`, `channel.SoftwareFilter` is forcibly set to `"none"` before reading data.
4. **Statistics Default**: `MinY`, `MaxY`, `AvgY` default to `Strings.Table_NA` (not empty string).
5. **PSD Data Length**: PSD processing resizes input arrays to the nearest enclosing power of 2 via `Utils.GetEnclosingPower2()`.
6. **Frequency Array First Element**: In PSD mode, `freq[0]` is explicitly set to `1` after calculation.
7. **IEPE Bridge Excitation**: Channels with `Bridge == "IEPE"` display `"---"` for excitation instead of measured voltage.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base` - `BasePropertyChanged` base class
- `DTS.Common.Enums.Sensors` - `SensorConstants` for bridge type detection
- `DTS.Common.Enums.Viewer` - `ChartUnitTypeEnum`, `TimeUnitTypeEnum`, window/filter enums
- `DTS.Common.Enums.DASFactory` - `DFConstantsAndEnums.RecordingMode`
- `DTS.Common.Interface` - `ITestDataSeries`, `ITestChannel`, `IGraphViewModel`, `IChartOptionsModel`, `IBaseModel`, `IPSDReportSettingsModel`
- `DTS.Common.Strings` - Localized string constants (`Table_NA`, `Envelope`, etc.)
- `DTS.Common.Utils` - `Utils.GetEnclosingPower2()`
- `DTS.Common.Utilities` - `RecordingModeExtensions`
- `DTS.Common.Utilities.Logging` - `APILogger`
- `DTS.Common.Converters` - `EnumDescriptionTypeConverter`
- `DTS.Common.Events` - `GraphChannelReadCalcProgressChangedEvent`, `GraphChannelReadCalcProgressChangedEventArgs`
- `DTS.Common.Exceptions` - `OutOfDataException`
- `Prism.Events` - `IEventAggregator`
- `System.Windows.Media` - `Brush`, `SolidColorBrush`, `Color`, `Colors`
- `FftSharp` - `Transform.PSD_Welch()`, `Transform.FFTfreq()`, `WindowType`, `WindowAveragingType`
- `Exocortex.DSP` - `PassFilter.LowPass()`, `PassFilter.HighPass()`, `PassFilterType`
- `Serialization.SliceRaw.File.Reader` - `ReadChannelsBinaryData()` (external/unclear origin)
### Dependents (Inferred):
- Any view or view model that displays graph data and implements `IGraphViewModel`
- PSD report generation components
---
## 5. Gotchas
1. **Async Methods Are Not Async**: Both `GetTestDataAsync` overloads are marked `async` but contain no `await` operators. They execute synchronously despite the method signature. Compiler warning CS1998 is suppressed with pragmas.
2. **GraphColor Allocation on Every Access**: The `GraphColor` getter instantiates a new `SolidColorBrush` on every call. Frequent access in UI binding scenarios may cause unnecessary allocations.
3. **T0EUValue Naming Misnomer**: Per source comment: *"this is the T0 value regardless of units ... it's not really EU but since it's already in use I'm not going to change it"*. The property name is misleading.
4. **PSD Envelope Requires Non-Empty Input**: `GetEnvelopeChannel()` returns an empty `TestDataSeries` if input list is null or empty, without any error indication.
5. **Channel Error Short-Circuit**: `AddTestChannelToChart()` returns `null` (not an exception) if `channel.ErrorMessage` is non-empty, which may cause null reference exceptions in callers not expecting null.
6. **Digital Channel Detection String Comparison**: Digital channels are detected via `channel.Bridge.StartsWith(SensorConstants.BridgeType.DigitalInput.ToString())`. This relies on `ToString()` matching the enum name exactly.
7. **GRMS Calculation Edge Case**: `CalculateGRMS()` uses `N.EqualsDigitPrecision(-1, 1)` for a special case. The method `EqualsDigitPrecision` is not defined in the provided source—its behavior is unclear.
8. **Frequency Array Mutation**: In PSD mode, `freq[0] = 1` mutates the array returned from `FftSharp.Transform.FFTfreq()`. This may affect any other consumers of that array if it's shared.

View File

@@ -0,0 +1,82 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Properties/AssemblyInfo.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Properties/Annotations.cs
generated_at: "2026-04-16T13:52:16.308869+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "530eff79443974f8"
---
# Module Documentation: DTS.Viewer.Graph Properties
## 1. Purpose
This module component provides assembly-level configuration and static analysis support for the `DTS.Viewer.Graph` assembly. `AssemblyInfo.cs` establishes the assembly's identity, version (1.0.0.0), and COM visibility settings. `Annotations.cs` defines a comprehensive suite of custom attributes (sourced from JetBrains) used to enhance code inspection, nullability analysis, and framework-specific validations (ASP.NET MVC, Razor, XAML) within the codebase, enabling deeper static analysis without requiring external dependencies.
## 2. Public Interface
### Assembly Metadata (AssemblyInfo.cs)
These attributes configure the compiled assembly `DTS.Viewer.Graph.dll`.
* **`AssemblyTitle`**: Set to `"Graph"`.
* **`AssemblyProduct`**: Set to `"Graph"`.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
* **`Guid`**: Set to `"61261c58-c32e-4dea-a87a-d7f956f28b4d"`.
* **`ComVisible`**: Set to `false`.
### Code Annotations (Annotations.cs)
The following attributes are defined in the `DTS.Viewer.Graph.Annotations` namespace. They are intended for use by static analysis tools (e.g., ReSharper, Rider) and the compiler.
**Nullability & Contracts:**
* **`CanBeNullAttribute`**: Indicates a value might be `null`.
* **`NotNullAttribute`**: Indicates a value should never be `null`.
* **`ItemNotNullAttribute`**: Indicates collection items or `Task.Result` are not `null`.
* **`ItemCanBeNullAttribute`**: Indicates collection items or `Task.Result` might be `null`.
* **`ContractAnnotationAttribute`**: Defines method input/output contracts (e.g., `null => halt`).
* **`PureAttribute`**: Marks a method as having no observable side effects.
**Usage & Visibility:**
* **`PublicAPIAttribute`**: Marks a type/member as part of the public API, preventing "unused" warnings.
* **`UsedImplicitlyAttribute`**: Indicates a symbol is used via reflection or external means.
* **`MeansImplicitUseAttribute`**: Applied to other attributes to indicate that targets should be considered "used".
* **`BaseTypeRequiredAttribute`**: Enforces that a type marked with a specific attribute must inherit from a specific base type.
**Method Behavior:**
* **`StringFormatMethodAttribute`**: Marks a method parameter as a format string (e.g., for `string.Format` validation).
* **`NotifyPropertyChangedInvocatorAttribute`**: Marks a method as raising the `PropertyChanged` event.
* **`InstantHandleAttribute`**: Indicates a delegate parameter is executed during the method call.
* **`MustUseReturnValueAttribute`**: Warns if the method's return value is ignored.
* **`CollectionAccessAttribute`**: Describes how a method modifies a collection (Read, Modify, Update).
* **`AssertionMethodAttribute` / `AssertionConditionAttribute`**: Marks methods that halt execution based on conditions (e.g., assertion methods).
**Framework Specific (ASP.NET, Razor, XAML):**
* **`AspMvcActionAttribute`, `AspMvcControllerAttribute`, `AspMvcViewAttribute`**: Assist in resolving MVC references.
* **`RazorSectionAttribute`, `RazorImportNamespaceAttribute`**: Assist in Razor view analysis.
* **`XamlItemsControlAttribute`, `XamlItemBindingOfItemsControlAttribute`**: Assist in XAML `DataContext` resolution.
**Miscellaneous:**
* **`SourceTemplateAttribute`**: Marks an extension method as a source template for code completion.
* **`MacroAttribute`**: Defines macros for source template parameters.
* **`NoReorderAttribute`**: Prevents code cleanup tools from reordering members.
## 3. Invariants
* **COM Visibility:** The assembly is explicitly configured with `ComVisible(false)`, ensuring types are not exposed to COM by default.
* **Version Consistency:** The `AssemblyVersion` and `AssemblyFileVersion` are both strictly defined as `1.0.0.0`.
* **Attribute Usage:** All annotation attributes are strictly constrained by `AttributeUsage` attributes. For example, `PureAttribute` can only target `Method`s, while `CanBeNullAttribute` can target methods, parameters, properties, delegates, fields, events, classes, interfaces, and generic parameters.
* **Licensing:** The `Annotations.cs` file is explicitly licensed under the MIT License (Copyright 2016 JetBrains), requiring the license notice to be preserved in copies.
## 4. Dependencies
* **System Dependencies:**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* `System`
* **Tooling Dependencies:** The annotations in `Annotations.cs` are designed to be consumed by JetBrains static analysis tools (ReSharper, Rider). They have no runtime impact on the application logic itself.
* **Consumers:** This module is a foundational block for the `DTS.Viewer.Graph` project. Other projects referencing `DTS.Viewer.Graph` may utilize these annotations if exposed publicly, though they are primarily for internal analysis.
## 5. Gotchas
* **Obsolete Assertion Attribute:** The `TerminatesProgramAttribute` is marked `[Obsolete("Use [ContractAnnotation('=> halt')] instead")]`. Developers should avoid using this attribute in new code and prefer `ContractAnnotationAttribute`.
* **Hardcoded Version:** The version `1.0.0.0` is hardcoded in `AssemblyInfo.cs`. If this project uses CI/CD pipelines that typically auto-increment versions or use MSBuild properties (e.g., `1.0.*`), this file overrides that behavior, potentially requiring manual updates for new releases.
* **Duplicate Annotations:** The `Annotations.cs` file is a standard "copy-paste" of JetBrains annotations. If other modules in the solution (e.g., `DTS.Viewer.Core`) also include this file, there may be duplicate attribute definitions if namespaces are not carefully managed or if the `global` namespace is used, though here they are safely scoped to `DTS.Viewer.Graph.Annotations`.
* **Empty Description:** The `AssemblyDescription` attribute is an empty string, offering no metadata regarding the specific functionality of the Graph module.

View File

@@ -0,0 +1,71 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:51:30.707906+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ea967aac84c55893"
---
# Documentation: DTS.Viewer.Graph Resources
## 1. Purpose
This module provides localization support for the `DTS.Viewer.Graph` namespace. It consists of a WPF markup extension (`TranslateExtension`) for declarative XAML binding and an auto-generated resource accessor class (`StringResources`) for retrieving localized strings programmatically. The module centralizes user-facing strings related to graph operations, data filtering errors, and file export statuses (PDF/CSV).
## 2. Public Interface
### Class: `TranslateExtension`
**Namespace:** `DTS.Viewer.Graph`
**Inheritance:** `System.Windows.Markup.MarkupExtension`
This class allows XAML bindings to localized resources.
* **Constructor**
* `public TranslateExtension(string key)`: Initializes the extension with the resource key to look up.
* **Method**
* `public override object ProvideValue(IServiceProvider serviceProvider)`: Returns the localized string associated with `_key`. If the key is null or empty, it returns the constant `#stringnotfound#`. If the key is valid but no resource is found, it returns `#stringnotfound#` appended with the key name.
### Class: `StringResources`
**Namespace:** `DTS.Viewer.Graph.Resources`
**Visibility:** `internal`
A strongly-typed resource class generated by Visual Studio tools.
* **Property: `ResourceManager`** (static)
* Returns the cached `System.Resources.ResourceManager` instance for this assembly.
* **Property: `Culture`** (static)
* Gets or sets the `System.Globalization.CultureInfo` used for resource lookups.
* **Resource String Properties** (static, read-only):
* `BadDataFromCustomFilter`: Warning regarding filter class frequency exceeding sample rate bounds.
* `BadDataFromTestSetupDefaultFilter`: Warning regarding test filter results causing out-of-bounds data.
* `BadDataUnfilteredUnknown`: Error message for unviewable channel data.
* `ReadingChannelData`: Status message indicating channel data is being read.
* `SavePDFError`: Error message for PDF chart save failure.
* `SavePDFSuccess`: Success message for PDF chart save (includes format placeholders `{0}`, `{1}`, etc.).
* `SaveReportCSVError`: Error message for CSV report save failure.
* `SaveReportCSVSuccess`: Success message for CSV report save.
* `SaveReportPDFError`: Error message for PDF report save failure.
* `SaveReportPDFSuccess`: Success message for PDF report save.
## 3. Invariants
* **Null Safety:** `TranslateExtension.ProvideValue` will never return null. It guarantees a string return, defaulting to specific error constants if lookup fails.
* **Error Differentiation:** The return value distinguishes between a missing key argument (returns `#stringnotfound#`) and a valid key argument with no matching resource (returns `#stringnotfound# [key]`).
* **Resource Availability:** `StringResources` assumes the existence of a corresponding `.resx` file embedded in the assembly manifest named `"DTS.Viewer.Graph.Resources.StringResources"`.
## 4. Dependencies
* **Internal Dependencies:**
* `TranslateExtension` depends entirely on `DTS.Viewer.Graph.Resources.StringResources` for data retrieval.
* **External Dependencies:**
* `System`: Core base library.
* `System.Windows.Markup`: Required for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute` (WPF specific).
* `System.Resources`: Used for `ResourceManager`.
* `System.Globalization`: Used for `CultureInfo`.
* **Dependents:**
* Unknown from source alone. However, the `MarkupExtensionReturnType` attribute implies consumption by WPF XAML parsers within the `DTS.Viewer.Graph` module.
## 5. Gotchas
* **Auto-Generated Code:** `StringResources` is a designer file (`StringResources.Designer.cs`). Manual edits to this file will be overwritten by the tooling (Visual Studio/ResGen). Changes must be made to the underlying `.resx` file.
* **Internal Visibility:** The `StringResources` class is marked `internal`. It is not accessible outside the `DTS.Viewer.Graph` assembly.
* **Silent Failure Mode:** `TranslateExtension` does not throw exceptions for missing keys. Instead, it returns the literal string `#stringnotfound#`. Developers debugging missing UI text must search for this specific string or check the output for the appended key name.
* **Hardcoded Fallback:** The fallback string `#stringnotfound#` is hardcoded in `TranslateExtension.cs` rather than being localized itself.

View File

@@ -0,0 +1,110 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/GraphView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/TestDataView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/View/TestDataSeriesView.xaml.cs
generated_at: "2026-04-16T13:53:01.641041+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "8c5a8096c69954ca"
---
# Documentation: DTS.Viewer.Graph Views
## 1. Purpose
This module provides WPF view components for graph visualization within the DTS Viewer application. It contains three XAML code-behind classes—`GraphView`, `TestDataView`, and `TestDataSeriesView`—that implement corresponding interfaces from `DTS.Common.Interface`. The primary functionality includes rendering charts using ComponentOne WPF Chart controls and exporting test data to PDF and CSV formats with associated metadata (test setup information, gRMS tables, and PSD data).
---
## 2. Public Interface
### GraphView
**Implements:** `IGraphView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public GraphView()` | Initializes the XAML component via `InitializeComponent()`. |
---
### TestDataView
**Implements:** `ITestDataView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestDataView()` | Initializes the XAML component via `InitializeComponent()`. |
**Note:** Contains extensive commented-out code for mouse-driven zoom functionality (`MainChart_MouseLeftButtonDown`, `MainChart_MouseMove`, `MainChart_MouseLeftButtonUp`, `PerformZoom`, `DrawReversibleRectangle`), but none of this is active.
---
### TestDataSeriesView
**Implements:** `ITestDataSeriesView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestDataSeriesView()` | Initializes the XAML component via `InitializeComponent()`. |
| SaveReportToPDF | `public bool SaveReportToPDF(string directory)` | Generates a PDF containing: test setup info, chart image, and a gRMS table with channel names, sample rates, and gRMS values. Returns `true` on success, `false` on failure. |
| SaveReportToCSV | `public bool SaveReportToCSV(string directory)` | Exports chart data to CSV format with frequency (Hz) and PSD values (EngineeringUnits²/Hz). Returns `true` on success, `false` on failure. |
| obj_DataPointChanged | `private void obj_DataPointChanged(object sender, EventArgs e)` | Event handler for data point changes. **All logic is commented out.** |
| MainChart_OnMouseWheel | `private void MainChart_OnMouseWheel(object sender, MouseWheelEventArgs e)` | Mouse wheel event handler. **All logic is commented out.** |
| MainChart_OnKeyUp | `private void MainChart_OnKeyUp(object sender, KeyEventArgs e)` | Key up event handler. **Empty implementation.** |
---
### AxisExtension (Static Extension Class)
| Member | Signature | Description |
|--------|-----------|-------------|
| GetDispMin | `public static double GetDispMin(this Axis axis)` | Calculates display minimum: `axis.ActualMin + axis.Value * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale)` |
| GetDispMax | `public static double GetDispMax(this Axis axis)` | Calculates display maximum: `axis.ActualMax - (1 - axis.Value) * (axis.ActualMax - axis.ActualMin) * (1 - axis.Scale)` |
---
## 3. Invariants
- **SaveReportToPDF**: The `directory` parameter must be non-null and non-whitespace; otherwise, a `DirectoryNotFoundException` is thrown.
- **SaveReportToCSV**: The method creates the target directory if it does not exist.
- **DataContext Requirement**: Both `SaveReportToPDF` and `SaveReportToCSV` require `MainChart.DataContext` to be castable to `TestDataSeriesViewModel` with a non-null `GraphDataSeries` property.
- **PDF Paper Size**: Determined by `System.Globalization.RegionInfo.CurrentRegion.IsMetric` — A4 for metric regions, Letter otherwise.
- **CSV Data Alignment**: The CSV export loop assumes all series in `GraphDataSeries` have `Xvalue` and `Yvalue` arrays of equal or greater length than the iteration index.
---
## 4. Dependencies
### External Dependencies (Imports)
| Namespace | Purpose |
|-----------|---------|
| `DTS.Common.Interface` | Provides `IGraphView`, `ITestDataView`, `ITestDataSeriesView` interfaces |
| `DTS.Common.Utilities.Logging` | Provides `APILogger` for logging operations |
| `DTS.Common.Utils` | Provides `FileUtils.GetEncoding()` for text encoding |
| `C1.WPF.Chart` / `C1.WPF.C1Chart` / `C1.WPF.C1Chart.Extended` | ComponentOne chart controls (`C1FlexChart`, `Axis`, `ImageFormat`) |
| `C1.WPF.Pdf` | ComponentOne PDF generation (`C1PdfDocument`, `PaperKind`, `Font`, `Pen`) |
| `System.Windows` | WPF core types (`Point`, `Rect`, `Visibility`, `MessageBox`, etc.) |
| `System.Windows.Input` | Input types (`MouseEventArgs`, `MouseWheelEventArgs`, `KeyEventArgs`, `ModifierKeys`) |
| `System.Windows.Media.Imaging` | Bitmap types (`BitmapImage`, `WriteableBitmap`) |
### Downstream Dependencies
- **Unclear from source alone** — These are view components; consumers would typically be ViewModels or other presentation-layer components that reference these views, but no direct consumers are visible in the provided source.
---
## 5. Gotchas
1. **Substantial Commented-Out Code**: Both `TestDataView` and `TestDataSeriesView` contain significant commented-out functionality (zoom/pan features, data point tracking). This suggests incomplete features or deprecated functionality that was never removed.
2. **Direct Concrete Type Cast**: `SaveReportToPDF` and `SaveReportToCSV` cast `MainChart.DataContext` directly to `TestDataSeriesViewModel` (a concrete class) rather than an interface. This tight coupling could cause runtime exceptions if the DataContext type changes.
3. **Unsafe GraphColor Cast**: In `SaveReportToPDF`, `ds.GraphColor` is cast directly to `SolidColorBrush` without null or type checking:
```csharp
pdf.FillRectangle((ds.GraphColor as System.Windows.Media.SolidColorBrush).Color, ...);
```
This will fail silently or throw if `GraphColor` is null or a different brush type.
4. **Empty Event Handlers**: `MainChart_OnKeyUp` is entirely empty, and `obj_DataPointChanged` / `MainChart_OnMouseWheel` have all logic commented out. These handlers may be wired up in XAML but do nothing.
5. **CSV Filename Suffix**: CSV files are saved with `.PSD.csv` extension, indicating Power Spectral Density data, but this is not validated against actual data content.
6. **Encoding Fallback**: `SaveReportToCSV` catches exceptions when getting encoding and falls back to `Encoding.Default`, which may produce inconsistent file encodings across different systems.

View File

@@ -0,0 +1,123 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Graph/ViewModel/GraphViewModel.cs
generated_at: "2026-04-16T13:51:13.371255+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "cd4107fac05f80cd"
---
# GraphViewModel Documentation
## 1. Purpose
`GraphViewModel` is a ViewModel within the `DTS.Viewer.Graph` module that manages graph visualization and coordinates data series display. It serves as a mediator between parent ViewModels (`IViewerMainViewModel` or `IPSDReportMainViewModel`) and the graph rendering components, handling event-driven communication for channel selection, test summaries, and data loading progress. The class follows the MVVM pattern using Prism and Unity, providing bindable properties for UI state management and interaction requests for user notifications.
---
## 2. Public Interface
### Constructor
```csharp
public GraphViewModel(
IGraphView view,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the ViewModel, sets the View's DataContext, and creates `NotificationRequest` and `ConfirmationRequest` instances.
### Public Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IGraphView` | The associated graph view instance. |
| `Parent` | `IBaseViewModel` (internal) | Reference to the parent ViewModel. |
| `DataSeriesView` | `ITestDataSeriesView` | The data series view used for chart rendering. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for displaying notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for displaying confirmations. |
| `ContextGraphRegion` | `object` | Gets/sets the content of the `GraphRegion` on the View. |
| `MessageText` | `string` | User-facing message text. Default: `"Please select Event(s) to export data"`. |
| `MessageVisibility` | `bool` | Controls visibility of the message panel. |
| `ProgressPercent` | `double` | Progress percentage for data loading operations. Default: `0D`. |
| `ProgressText` | `string` | Progress message text. Default: `"Reading channel data..."`. |
| `ProgressVisibility` | `bool` | Controls visibility of the progress indicator. |
| `GraphInfoVisibility` | `bool` | Controls visibility of graph information. |
| `GraphVisibility` | `bool` | Computed as `!MessageVisibility`. |
| `HeaderInfo` | `string` | Returns constant `"GraphRegion"`. |
| `IsBusy` | `bool` | Busy state indicator. |
| `IsDirty` | `bool` | Always returns `false` (read-only). |
### Public Methods
```csharp
public override void Initialize()
```
Empty override; performs no initialization.
```csharp
public override void Initialize(object parameter)
```
Performs context-specific initialization based on `parameter` type:
- If `parameter` is `IViewerMainViewModel`: Calls `Subscribe()` and initializes `DataSeriesView`.
- If `parameter` is `Tuple<IBaseViewModel, string>` where `Item1` is `IPSDReportMainViewModel`: Calls `SubscribeDataSelect()` or `SubscribeResult()` based on `Item2` value, and configures chart scrollbars/actions accordingly.
---
## 3. Invariants
- **`IsDirty`** always returns `false` and cannot be modified.
- **`HeaderInfo`** always returns the string `"GraphRegion"`.
- **`GraphVisibility`** is always the logical inverse of `MessageVisibility`.
- Event handlers (`OnTestSelectedCountChanged`, `OnGraphSelectedCountChanged`, `OnGraphChannelsReadCompleted`, `OnGraphChannelReadCalcProgressChangedEvent`) check that `Parent` or `this` matches the event argument's source before processing.
- `OnGraphChannelsReadCompleted` returns early if `arg` is `null`.
- `OnGraphChannelReadCalcProgressChangedEvent` only updates `ProgressPercent` if the value is `>= 0`.
---
## 4. Dependencies
### This Module Depends On
| Namespace | Purpose |
|-----------|---------|
| `C1.WPF.C1Chart` | ComponentOne charting controls (`AxisScrollBar`). |
| `DTS.Common.Base` | Base classes (`BaseViewModel<T>`, `IBaseModel`, `IBaseViewModel`). |
| `DTS.Common.Events` | Event types: `RaiseNotification`, `GraphSelectedChannelCountNotification`, `TestSummaryCountNotification`, `TestModificationChangedEvent`, `GraphChannelsReadCompletedNotification`, `GraphChannelReadCalcProgressChangedEvent`. |
| `DTS.Common.Interactivity` | `InteractionRequest<T>`, `Notification`, `Confirmation`. |
| `DTS.Common.Interface` | `IGraphViewModel`, `ITestDataSeriesView`, `ITestDataSeriesViewModel`, `IViewerMainViewModel`, `IPSDReportMainViewModel`. |
| `Prism.Events` | `IEventAggregator`, `ThreadOption`. |
| `Prism.Regions` | `IRegionManager`. |
| `Unity` | `IUnityContainer`. |
### External Types Referenced (Not Defined Here)
- `GraphView` - Concrete view type cast in `ContextGraphRegion` property.
- `TestDataSeriesView` - Concrete data series view cast for chart configuration.
- `TestDataSeriesViewModel` - Concrete ViewModel cast for calling `SubscribePSD()`.
- `ITestModificationModel` - Parameter type for `OnTestModificationChanged`.
- Various event argument types: `TestSummaryCountNotificationArg`, `GraphSelectedChannelCountNotificationArg`, `NotificationContentEventArgs`, `GraphChannelsReadCompletedNotificationArgs`, `GraphChannelReadCalcProgressChangedEventArgs`.
---
## 5. Gotchas
1. **Member Hiding with `new` Keyword**: The class uses `new` to hide multiple base class members (`Model`, `ConfirmationRequest`, `PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`). This can cause unexpected behavior when casting to base types.
2. **Code Duplication in Subscribe Methods**: `Subscribe()`, `SubscribeDataSelect()`, and `SubscribeResult()` have nearly identical implementations. The only difference is `Subscribe()` includes `TestModificationChangedEvent` subscription, while the others do not—but `OnTestModificationChanged` is an empty method body.
3. **Empty Event Handler**: `OnTestModificationChanged(ITestModificationModel obj)` is subscribed but contains no implementation.
4. **Concrete Type Casting**: The code casts interfaces to concrete types (`GraphView`, `TestDataSeriesView`, `TestDataSeriesViewModel`) which breaks abstraction and could cause runtime failures if implementations change:
```csharp
((AxisScrollBar)((TestDataSeriesView)DataSeriesView).MainChart.View.AxisX.ScrollBar).Visibility = ...
((TestDataSeriesView)DataSeriesView).MainChart.Actions.Clear();
((TestDataSeriesViewModel)viewModel).SubscribePSD();
```
5. **Hardcoded String Comparisons**: The `Initialize(object parameter)` method uses string literals (`"DataSelect"`, `"Graph"`) for control flow, which is fragile.
6. **Unused Private Field**: The `Model` property is set but never accessed elsewhere in the visible code.
7. **ReSharper Suppressions**: The file contains numerous ReSharper directive suppressions, suggesting known code quality issues that were disabled rather than addressed.

View File

@@ -0,0 +1,157 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/GraphListModule.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/ExportGraphListModule.cs
generated_at: "2026-04-16T13:42:43.875292+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "267c5c22d55f0847"
---
# Documentation: GraphList and ExportGraphList Modules
## 1. Purpose
This documentation covers two related Prism modules within the DTS Viewer application: `GraphListModule` and `ExportGraphListModule`. Both modules serve as plugin-like components that register their respective views and view models with the Unity dependency injection container at application startup. They expose assembly metadata (name, image, group, region) through custom attributes, enabling the main application shell to discover and display them as available components. The modules appear to provide graph visualization/listing functionality, with the export variant likely offering a specialized view for exporting graph data.
---
## 2. Public Interface
### GraphListModule Class
**Namespace:** `DTS.Viewer.GraphList`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GraphListModule(IUnityContainer unityContainer)` | Accepts an injected Unity container instance and stores it in `_unityContainer`. |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Implements `IModule.RegisterTypes`. Delegates to `Initialize()`. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Implements `IModule.OnInitialized`. Currently empty (no-op). |
| `Initialize` | `void Initialize()` | Registers `IGraphMainView``GraphMainView` and `IGraphMainViewModel``GraphMainViewModel` with the Unity container. |
### GraphListNameAttribute Class
**Namespace:** `DTS.Viewer.GraphList`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GraphListNameAttribute()` | Default constructor. |
| Constructor | `GraphListNameAttribute(string s)` | Overloaded constructor accepting a string parameter (unused). Sets `_assemblyName` to `AssemblyNames.GraphList.ToString()`. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns the stored assembly name. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(TextAttribute)`. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property value. |
### GraphListImageAttribute Class
**Namespace:** `DTS.Viewer.GraphList`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GraphListImageAttribute()` | Default constructor. |
| Constructor | `GraphListImageAttribute(string s)` | Overloaded constructor. Loads image via `AssemblyInfo.GetImage(AssemblyNames.GraphList.ToString())`. |
| `AssemblyImage` | `override BitmapImage AssemblyImage { get; }` | Lazy-loads and returns the assembly image. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `AssemblyNames.GraphList.ToString()`. |
| `AssemblyGroup` | `override string AssemblyGroup { get; }` | Returns `eAssemblyGroups.Viewer.ToString()`. |
| `AssemblyRegion` | `override eAssemblyRegion AssemblyRegion { get; }` | Returns `eAssemblyRegion.GraphListRegion`. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(ImageAttribute)`. |
| `GetAssemblyImage` | `override BitmapImage GetAssemblyImage()` | Returns `AssemblyImage` property. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property. |
| `GetAssemblyGroup` | `override string GetAssemblyGroup()` | Returns `AssemblyGroup` property. |
| `GetAssemblyRegion` | `override eAssemblyRegion GetAssemblyRegion()` | Returns `AssemblyRegion` property. |
---
### ExportGraphListModule Class
**Namespace:** `DTS.Viewer.Export`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ExportGraphListModule(IUnityContainer unityContainer)` | Accepts an injected Unity container instance and stores it in `_unityContainer`. |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Implements `IModule.RegisterTypes`. Delegates to `Initialize()`. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Implements `IModule.OnInitialized`. Currently empty (no-op). |
| `Initialize` | `void Initialize()` | Registers `IExportGraphMainView``ExportGraphMainView` and `IExportGraphMainViewModel``ExportGraphMainViewModel` with the Unity container. |
### ExportGraphListNameAttribute Class
**Namespace:** `DTS.Viewer.Export`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ExportGraphListNameAttribute()` | Default constructor. |
| Constructor | `ExportGraphListNameAttribute(string s)` | Overloaded constructor accepting a string parameter (unused). Sets `_assemblyName` to `AssemblyNames.GraphList.ToString()`. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns the stored assembly name. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(TextAttribute)`. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property value. |
### ExportGraphListImageAttribute Class
**Namespace:** `DTS.Viewer.Export`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `ExportGraphListImageAttribute()` | Default constructor. |
| Constructor | `ExportGraphListImageAttribute(string s)` | Overloaded constructor. Loads image via `AssemblyInfo.GetImage(AssemblyNames.GraphList.ToString())`. |
| `AssemblyImage` | `override BitmapImage AssemblyImage { get; }` | Lazy-loads and returns the assembly image. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `AssemblyNames.GraphList.ToString()`. |
| `AssemblyGroup` | `override string AssemblyGroup { get; }` | Returns `eAssemblyGroups.Viewer.ToString()`. |
| `AssemblyRegion` | `override eAssemblyRegion AssemblyRegion { get; }` | Returns `eAssemblyRegion.GraphListRegion`. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(ImageAttribute)`. |
| `GetAssemblyImage` | `override BitmapImage GetAssemblyImage()` | Returns `AssemblyImage` property. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property. |
| `GetAssemblyGroup` | `override string GetAssemblyGroup()` | Returns `AssemblyGroup` property. |
| `GetAssemblyRegion` | `override eAssemblyRegion GetAssemblyRegion()` | Returns `AssemblyRegion` property. |
---
## 3. Invariants
- **Module Naming Convention:** `GraphListModule` has `ModuleName = "GraphList"`; `ExportGraphListModule` has `ModuleName = "ExportGraphList"`.
- **Attribute Application:** Both `GraphListNameAttribute`/`GraphListImageAttribute` and `ExportGraphListNameAttribute`/`ExportGraphListImageAttribute` are applied at assembly level with `AllowMultiple = false`.
- **Registration Pattern:** Both modules register interface-to-concrete-type mappings (view and view model) via `RegisterType<TInterface, TImplementation>()`.
- **Assembly Name Consistency:** Both attribute families return `AssemblyNames.GraphList.ToString()` for `AssemblyName`, despite `ExportGraphListModule` residing in a different namespace (`DTS.Viewer.Export`).
- **Region Assignment:** Both modules declare `eAssemblyRegion.GraphListRegion` as their target region.
- **Group Assignment:** Both modules declare `eAssemblyGroups.Viewer` as their assembly group.
---
## 4. Dependencies
### External Dependencies (Imports)
| Dependency | Usage |
|------------|-------|
| `System` | Core .NET types (`Type`, `AttributeUsage`, `AttributeTargets`). |
| `System.Windows.Media.Imaging` | `BitmapImage` for assembly images. |
| `DTS.Common` | `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion` enums; `AssemblyInfo` utility class. |
| `DTS.Common.Interface` | `TextAttribute`, `ImageAttribute` base classes. |
| `Prism.Ioc` | `IContainerProvider`, `IContainerRegistry` interfaces. |
| `Prism.Modularity` | `IModule` interface, `ModuleAttribute`. |
| `Unity` | `IUnityContainer` for dependency injection. |
### Internal Dependencies (Inferred)
| Dependency | Reason |
|------------|--------|
| `GraphMainView` | Concrete view class registered by `GraphListModule`. |
| `GraphMainViewModel` | Concrete view model class registered by `GraphListModule`. |
| `IGraphMainView` | Interface registered by `GraphListModule`. |
| `IGraphMainViewModel` | Interface registered by `GraphListModule`. |
| `ExportGraphMainView` | Concrete view class registered by `ExportGraphListModule`. |
| `ExportGraphMainViewModel` | Concrete view model class registered by `ExportGraphListModule`. |
| `IExportGraphMainView` | Interface registered by `ExportGraphListModule`. |
| `IExportGraphMainViewModel` | Interface registered by `ExportGraphListModule`. |
### Consumers (Inferred)
- The main application shell that discovers and loads Prism modules.
- Any code that reflects over assemblies looking for `TextAttribute` or `ImageAttribute` metadata.
---
## 5. Gotchas
1. **Duplicate Assembly Name:** `ExportGraphListModule` uses `AssemblyNames.GraphList.ToString()` for its `AssemblyName` property, identical to `GraphListModule`. This may cause ambiguity if the application shell uses assembly name to uniquely identify modules. It is unclear whether this is intentional (shared identity) or a bug.
2. **Shared Region:** Both modules target `eAssemblyRegion.GraphListRegion`. If the shell only supports one view per region, one module may overwrite or conflict with the other.
3. **Unused Constructor Parameter:** Both `*NameAttribute` and `*ImageAttribute` constructors accept a `string s` parameter that is never used. The parameter is ignored in all implementations.
4. **Redundant Getter Side Effects:** In `*ImageAttribute` classes, the `AssemblyImage` getter has a side effect: it assigns `_img` before returning it. This means `_img` is re-fetched from `AssemblyInfo.GetImage()` on every access, potentially causing unnecessary I/O or memory allocation if called repeatedly.
5. **Empty `OnInitialized`:** Both modules implement `OnInitialized` as a no-op. If module initialization logic is expected here, it is missing.
6. **`Initialize()` Called from `RegisterTypes()`:** The `Initialize()` method is called within `RegisterTypes()`, which is non-standard for Prism modules. Typically, type registration happens in `RegisterTypes()` and runtime initialization in `OnInitialized()`. This pattern works but conflates registration with initialization.
7. **Missing Singleton Registration:** The comments indicate "Register View & View-Model... as a singleton," but `RegisterType` is used without `ContainerControlledLifetimeManager`, which registers types as transient (new instance per resolve) by default in Unity. If singleton behavior is intended, this appears to be incorrect.

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.

View File

@@ -0,0 +1,113 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Navigation/NavigationModule.cs
generated_at: "2026-04-16T13:45:08.040619+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b8a48119ee42a5bd"
---
# Documentation: DTS.Viewer.Navigation Module
## 1. Purpose
This module provides navigation functionality for the DTS Viewer application. It is a Prism module (`NavigationModule`) responsible for registering the navigation view and view-model with the Unity dependency injection container. The module also defines assembly-level metadata attributes (`NavigationPropertiesNameAttribute`, `NavigationPropertiesImageAttribute`) that expose the module's name, icon, group, and region information to the main application shell for display and routing purposes.
---
## 2. Public Interface
### `NavigationModule` Class
A Prism `IModule` implementation that handles module initialization and type registration.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `NavigationModule(IUnityContainer unityContainer)` | Accepts a Unity container via dependency injection and stores it in a private readonly field `_unityContainer`. |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Implements `IModule.RegisterTypes`. Delegates to `Initialize()`. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Implements `IModule.OnInitialized`. Currently empty with no implementation. |
| `Initialize` | `void Initialize()` | Registers `INavigationView``NavigationView` and `INavigationViewModel``NavigationViewModel` mappings with Unity via `RegisterType<TFrom, TTo>()`. |
**Module Metadata:**
- Decorated with `[Module(ModuleName = "NavigationProperties")]`
---
### `NavigationPropertiesNameAttribute` Class
An assembly-level attribute extending `TextAttribute` that provides the module's display name.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `NavigationPropertiesNameAttribute()` | Default constructor. Sets `_assemblyName` to `AssemblyNames.Navigation.ToString()`. |
| Constructor | `NavigationPropertiesNameAttribute(string s)` | Overloaded constructor accepting a string parameter (parameter is unused). |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `_assemblyName` (value of `AssemblyNames.Navigation.ToString()`). |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(TextAttribute)`. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property value. |
**Attribute Usage:** `AttributeTargets.Assembly`, `AllowMultiple = false`
---
### `NavigationPropertiesImageAttribute` Class
An assembly-level attribute extending `ImageAttribute` that provides the module's icon, name, group, and region metadata.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `NavigationPropertiesImageAttribute()` | Default constructor. Initializes `_img` via `AssemblyInfo.GetImage(AssemblyNames.Navigation.ToString())`. |
| Constructor | `NavigationPropertiesImageAttribute(string s)` | Overloaded constructor accepting a string parameter (parameter is unused). |
| `AssemblyImage` | `override BitmapImage AssemblyImage { get; }` | Getter re-assigns `_img` via `AssemblyInfo.GetImage(...)` then returns it. |
| `AssemblyName` | `override string AssemblyName { get; }` | Returns `AssemblyNames.Navigation.ToString()`. |
| `AssemblyGroup` | `override string AssemblyGroup { get; }` | Returns `eAssemblyGroups.Viewer.ToString()`. |
| `AssemblyRegion` | `override eAssemblyRegion AssemblyRegion { get; }` | Returns `eAssemblyRegion.NavigationRegion`. |
| `GetAttributeType` | `override Type GetAttributeType()` | Returns `typeof(ImageAttribute)`. |
| `GetAssemblyImage` | `override BitmapImage GetAssemblyImage()` | Returns `AssemblyImage` property. |
| `GetAssemblyName` | `override string GetAssemblyName()` | Returns `AssemblyName` property. |
| `GetAssemblyRegion` | `override eAssemblyRegion GetAssemblyRegion()` | Returns `AssemblyRegion` property. |
| `GetAssemblyGroup` | `override string GetAssemblyGroup()` | Returns `AssemblyGroup` property. |
**Attribute Usage:** `AttributeTargets.Assembly`, `AllowMultiple = false`
---
## 3. Invariants
- The module must be instantiated with a non-null `IUnityContainer` reference (constructor injection).
- `NavigationView` and `NavigationViewModel` must implement `INavigationView` and `INavigationViewModel` interfaces respectively (required for `RegisterType<,>()` calls).
- Assembly attributes are applied exactly once per assembly (`AllowMultiple = false`).
- The enum values `AssemblyNames.Navigation`, `eAssemblyGroups.Viewer`, and `eAssemblyRegion.NavigationRegion` must be defined in external assemblies (`DTS.Common`).
- The static method `AssemblyInfo.GetImage(string)` must be available and return a valid `BitmapImage`.
---
## 4. Dependencies
### This Module Depends On:
- **Prism.Ioc** — `IContainerProvider`, `IContainerRegistry`
- **Prism.Modularity** — `IModule`, `ModuleAttribute`
- **Unity** — `IUnityContainer`
- **System.Windows.Media.Imaging** — `BitmapImage`
- **DTS.Common** — `AssemblyNames` (enum), `eAssemblyRegion` (enum), `eAssemblyGroups` (enum), `AssemblyInfo` (static class with `GetImage` method)
- **DTS.Common.Interface** — `TextAttribute`, `ImageAttribute` (base classes)
### What Depends On This Module:
- **`NavigationView`** — Concrete view class (referenced but not defined in this file)
- **`NavigationViewModel`** — Concrete view-model class (referenced but not defined in this file)
- **`INavigationView`** — Interface (referenced but not defined in this file)
- **`INavigationViewModel`** — Interface (referenced but not defined in this file)
- The main application shell (consumes assembly attributes for module discovery and display)
---
## 5. Gotchas
1. **Misleading Comment:** The comment on line 38 states "Register View & View-Model with Unity dependency injection container as a singleton." However, `RegisterType<TFrom, TTo>()` registers types as **transient**, not singleton. To register as singleton, `RegisterSingleton<TFrom, TTo>()` or `RegisterInstance<T>()` should be used.
2. **Unused Constructor Parameters:** Both attribute classes have constructors accepting a `string s` parameter that is never used. This appears to be dead code, possibly required by attribute syntax conventions or leftover from refactoring.
3. **Side Effect in Property Getter:** The `AssemblyImage` property getter has a side effect—it reassigns `_img` every time it is called. This is unusual and could cause unnecessary image reloading if the property is accessed multiple times.
4. **Empty `OnInitialized` Implementation:** The `OnInitialized` method is intentionally empty. It is unclear whether this is by design or incomplete implementation.
5. **Redundant Method Call:** `RegisterTypes()` simply delegates to `Initialize()`. While this satisfies the Prism module contract, the separation between these methods serves no functional purpose in this implementation.

View File

@@ -0,0 +1,52 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Navigation/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:57:47.028867+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "24368b2aa50ace4f"
---
# Documentation: DTS.Viewer.Navigation Assembly Configuration
## 1. Purpose
This file provides assembly-level metadata and configuration for the `DTS.Viewer.Navigation` module. It defines the assembly's identity, version, and COM visibility settings using .NET attributes. This module appears to be a component of a larger "DTS Viewer" application, specifically handling navigation logic, though the specific implementation details are not contained within this file.
## 2. Public Interface
This file does not contain public classes, methods, or functions. It strictly defines assembly-level attributes.
**Assembly Attributes:**
* **`AssemblyTitle`**: Set to `"DTS.Viewer.Navigation"`.
* **`AssemblyDescription`**: Empty.
* **`AssemblyConfiguration`**: Empty.
* **`AssemblyCompany`**: Empty.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.Navigation"`.
* **`AssemblyCopyright`**: Set to `"Copyright © 2017"`.
* **`AssemblyTrademark`**: Empty.
* **`AssemblyCulture`**: Empty.
* **`ComVisible`**: Set to `false`. Types in this assembly are not visible to COM components.
* **`Guid`**: Set to `"237c6e9f-9118-4bec-a55a-e194232ac330"`.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
## 3. Invariants
* **COM Visibility:** The assembly is explicitly configured to prevent types from being exposed to COM components (`ComVisible(false)`).
* **Versioning:** Both the assembly version and file version are fixed at `1.0.0.0`.
* **Identity:** The assembly is identified by the GUID `237c6e9f-9118-4bec-a55a-e194232ac330`.
## 4. Dependencies
**Internal Dependencies (Imports):**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
**External Dependencies:**
* None identified from source alone. (This file acts as a configuration layer for the assembly itself).
**Dependents:**
* The main `DTS Viewer` application likely depends on this assembly, but this cannot be confirmed from this file alone.
## 5. Gotchas
* **Stale Copyright:** The `AssemblyCopyright` attribute contains a hardcoded year of 2017, which may be outdated.
* **SDK-Style Project Conflict:** If this project is migrated to a modern SDK-style `.csproj` format (.NET Core/.NET 5+), these attributes may cause build warnings (e.g., CS0579) because the SDK auto-generates these attributes by default. The file may need to be removed or the project configured to disable auto-generation of these attributes.
* **Missing Description:** The `AssemblyDescription` attribute is an empty string, providing no documentation on the assembly's purpose at the metadata level.

View File

@@ -0,0 +1,68 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Navigation/View/NavigationItem.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Navigation/View/NavigationView.xaml.cs
generated_at: "2026-04-16T13:57:48.771766+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "e298dba7e9bc3e6c"
---
# Documentation: DTS.Viewer.Navigation Views
## 1. Purpose
This module provides WPF view components for the navigation subsystem within the DTS Viewer application. It contains two code-behind classes—`NavigationItem` and `NavigationView`—that serve as the visual elements for rendering navigation items and the overall navigation container, respectively. These views follow the standard WPF code-behind pattern, delegating UI layout to their associated XAML files while implementing framework-specific interfaces for integration with the broader application architecture.
---
## 2. Public Interface
### `NavigationItem` (class)
**Namespace:** `DTS.Viewer.Navigation.View`
**Implements:** `IBaseView` (from `DTS.Common.Base`)
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public NavigationItem()` | Default constructor that initializes the XAML component via `InitializeComponent()`. |
---
### `NavigationView` (class)
**Namespace:** `DTS.Viewer.Navigation`
**Implements:** `INavigationView` (from `DTS.Common.Interface`)
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public NavigationView()` | Default constructor that initializes the XAML component via `InitializeComponent()`. |
---
## 3. Invariants
- Both classes are declared `partial`, indicating they are paired with XAML-generated partial classes at compile time.
- `InitializeComponent()` must be called in the constructor for each view; this is a WPF requirement for loading the associated XAML resource.
- `NavigationItem` must always implement `IBaseView`.
- `NavigationView` must always implement `INavigationView`.
- The namespaces differ: `NavigationItem` resides in `DTS.Viewer.Navigation.View`, while `NavigationView` resides directly in `DTS.Viewer.Navigation`.
---
## 4. Dependencies
### This module depends on:
- `DTS.Common.Base` — Provides the `IBaseView` interface used by `NavigationItem`.
- `DTS.Common.Interface` — Provides the `INavigationView` interface used by `NavigationView`.
- WPF infrastructure (implicit via `InitializeComponent()` and partial class pattern).
### What depends on this module:
- **Cannot be determined from source alone.** No downstream consumers are visible in these files. Likely consumers would be module initialization code, view models, or dependency injection containers within the `DTS.Viewer.Navigation` assembly or broader application.
---
## 5. Gotchas
- **Interface contracts are unknown:** The behaviors expected by `IBaseView` and `INavigationView` are not visible in these source files. Developers should consult `DTS.Common.Base` and `DTS.Common.Interface` for interface definitions.
- **No additional logic:** Both classes contain only initialization code. Any view-specific behavior (event handlers, data binding setup, etc.) is either in the XAML files or handled elsewhere (e.g., attached view models).
- **Namespace inconsistency:** `NavigationItem` is placed in a `.View` sub-namespace while `NavigationView` is not. This may be intentional or a historical inconsistency—verify project naming conventions before adding new views.
- **XAML files not provided:** The actual UI structure, visual states, and resource dictionaries for these views are defined in `NavigationItem.xaml` and `NavigationView.xaml`, which are not included in this source dump.

View File

@@ -0,0 +1,105 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.Navigation/ViewModel/NavigationViewModel.cs
generated_at: "2026-04-16T13:57:29.392045+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "17ac7f526470fc92"
---
# Documentation: NavigationViewModel
## 1. Purpose
The `NavigationViewModel` class serves as the view model for the navigation component within the DTS Viewer application. It acts as a mediator between the `INavigationView` and the application's navigation infrastructure, managing the content displayed in the navigation region and handling notification events via Prism's `IEventAggregator`. This class inherits from `BaseViewModel<INavigationViewModel>` and implements `INavigationViewModel`, providing data binding context for the navigation view and supporting interaction requests for notifications and confirmations.
---
## 2. Public Interface
### Constructor
```csharp
public NavigationViewModel(INavigationView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes a new instance of `NavigationViewModel`. Sets the view's `DataContext` to itself, creates new `NotificationRequest` and `ConfirmationRequest` instances, stores references to the event aggregator and Unity container, and subscribes to the `RaiseNotification` event.
---
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `NavigationView` | `INavigationView` | Gets the associated navigation view instance. Set once in constructor. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for displaying notifications to the user. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for displaying confirmation dialogs. Declared with `new` keyword. |
| `ContextNavigationRegion` | `object` | Gets or sets the content of the navigation region. Getter/setter directly access `((NavigationView)NavigationView).NavigationRegion.Content`. Raises `PropertyChanged` on set. |
| `HeaderInfo` | `string` | Returns the constant string `"NavigationRegion"`. |
| `IsBusy` | `bool` | Getter and setter both throw `NotImplementedException`. Declared with `new` keyword. |
| `IsDirty` | `bool` | Getter throws `NotImplementedException`. Declared with `new` keyword. |
| `IsNavigationIncluded` | `bool` | Get/set property. Declared with `new` keyword. |
---
### Methods
```csharp
public override void Initialize()
```
Overrides base `Initialize()`. Empty implementation.
```csharp
public override void Initialize(object parameter)
```
Overrides base `Initialize(object)`. Casts `parameter` to `IBaseViewModel` and assigns it to the private `Parent` property.
---
### Events
```csharp
public new event PropertyChangedEventHandler PropertyChanged
```
Event for property change notifications. Declared with `new` keyword, hiding the base class event.
---
## 3. Invariants
- `NavigationView` is assigned exactly once in the constructor and is never null thereafter (assumes constructor parameter is non-null).
- `NotificationRequest` and `ConfirmationRequest` are instantiated in the constructor and remain non-null for the lifetime of the view model.
- The `HeaderInfo` property always returns the literal string `"NavigationRegion"`.
- `IsBusy` and `IsDirty` properties will always throw `NotImplementedException` when accessed.
- The view model subscribes to `RaiseNotification` event during construction; the subscription persists for the object's lifetime.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base` — Provides `BaseViewModel<T>` and `IBaseViewModel`
- `DTS.Common.Events` — Provides `RaiseNotification` event and `NotificationContentEventArgs`
- `DTS.Common.Interactivity` — Provides `InteractionRequest<T>`, `Notification`, `Confirmation`
- `DTS.Common.Interface` — Provides `INavigationView`, `INavigationViewModel`
- `Prism.Events` — Provides `IEventAggregator`
- `Prism.Regions` — Provides `IRegionManager`
- `Unity` — Provides `IUnityContainer`
### What Depends On This Module:
- Cannot be determined from source alone. The `INavigationViewModel` interface suggests other modules may reference this view model through its interface abstraction.
---
## 5. Gotchas
1. **Multiple `new` keyword usages**: The properties `ConfirmationRequest`, `IsBusy`, `IsDirty`, `IsNavigationIncluded`, the `PropertyChanged` event, and the `OnPropertyChanged` method are all declared with `new`, hiding base class members. This indicates a design issue where the base class and derived class have conflicting member signatures. Callers casting to the base type will not see these overridden members.
2. **NotImplementedException on `IsBusy` and `IsDirty`**: Accessing either property will always throw. Code that attempts to bind to or check these properties will fail at runtime.
3. **Unused `ConfirmationRequest`**: The `ConfirmationRequest` property is instantiated but never raised anywhere in this class. It may be dead code or intended for future use.
4. **Concrete type cast in `ContextNavigationRegion`**: The property casts `INavigationView NavigationView` to the concrete type `NavigationView` to access `NavigationRegion.Content`. This breaks the interface abstraction and creates tight coupling to the concrete view implementation.
5. **`Parent` property never used**: The `Parent` property is set in `Initialize(object parameter)` but never referenced elsewhere in this file. Its purpose is unclear from source alone.
6. **Suppressed ReSharper warnings**: The file includes pragma-like comments suppressing warnings about unaccessed fields and unused auto-property accessors, suggesting known code quality issues that were silenced rather than resolved.

View File

@@ -0,0 +1,85 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/TestModificationModule.cs
generated_at: "2026-04-16T13:42:42.368236+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "3f67001eaa6ddf3a"
---
# Documentation: DTS.Viewer.TestModification Module
## 1. Purpose
This module serves as the entry point for the "TestModification" feature within the DTS Viewer application. It is a Prism Module (`IModule`) responsible for registering its associated View (`TestModificationView`) and ViewModel (`TestModificationViewModel`) with the Unity dependency injection container. Additionally, it defines assembly-level metadata attributes that expose the module's name, icon, grouping, and region assignment to the main application shell, enabling the module to be discovered and displayed in the UI.
## 2. Public Interface
### Classes
#### `TestModificationModule`
The main module class responsible for dependency injection registration.
* **`TestModificationModule(IUnityContainer unityContainer)`**
* Constructor that accepts a reference to the Unity container via dependency injection.
* **`void RegisterTypes(IContainerRegistry containerRegistry)`**
* Implements `IModule.RegisterTypes`. Calls the local `Initialize()` method to register views and view models.
* **`void OnInitialized(IContainerProvider containerProvider)`**
* Implements `IModule.OnInitialized`. Currently contains no implementation logic.
* **`void Initialize()`**
* Registers `ITestModificationView` to `TestModificationView` and `ITestModificationViewModel` to `TestModificationViewModel` with the Unity container.
#### `TestModificationModuleNameAttribute`
An assembly-level attribute providing the module's name as text.
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.TestModification`.
* **`Type GetAttributeType()`**
* Returns `typeof(TextAttribute)`.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property value.
#### `TestModificationModuleImageAttribute`
An assembly-level attribute providing image and categorization metadata for the module.
* **`BitmapImage AssemblyImage { get; }`**
* Retrieves the module's image via `AssemblyInfo.GetImage`.
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.TestModification`.
* **`string AssemblyGroup { get; }`**
* Returns `eAssemblyGroups.Viewer.ToString()`.
* **`eAssemblyRegion AssemblyRegion { get; }`**
* Returns `eAssemblyRegion.TestModificationRegion`.
* **`BitmapImage GetAssemblyImage()`**
* Returns the `AssemblyImage` property.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property.
* **`string GetAssemblyGroup()`**
* Returns the `AssemblyGroup` property.
* **`eAssemblyRegion GetAssemblyRegion()`**
* Returns the `AssemblyRegion` property.
## 3. Invariants
* **Module Name:** The module is identified by the string "TestModification" in the `[Module]` attribute.
* **Registration Mapping:** `ITestModificationView` is strictly mapped to `TestModificationView`, and `ITestModificationViewModel` is strictly mapped to `TestModificationViewModel`.
* **Attribute Usage:** Both custom attributes are decorated with `[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]`, ensuring they are applied only once per assembly.
* **Region Assignment:** The module is statically bound to `eAssemblyRegion.TestModificationRegion`.
## 4. Dependencies
### Internal Dependencies
* **`DTS.Common`**: Used for `AssemblyNames`, `AssemblyInfo`, `eAssemblyGroups`, and `eAssemblyRegion` enums/helpers.
* **`DTS.Common.Interface`**: Defines `TextAttribute` and `ImageAttribute`, which the custom attributes inherit from.
* **`DTS.Viewer.TestModification` (Local Namespace)**: The module references `TestModificationView`, `TestModificationViewModel`, and their interfaces (`ITestModificationView`, `ITestModificationViewModel`), which are expected to be defined elsewhere in this project/namespace.
### External Dependencies
* **`Prism.Ioc`**: Provides `IContainerProvider` and `IContainerRegistry`.
* **`Prism.Modularity`**: Provides the `IModule` interface and `ModuleAttribute`.
* **`Unity`**: Provides `IUnityContainer` for specific dependency injection implementation.
* **`System.Windows.Media.Imaging`**: Provides `BitmapImage` for module imagery.
## 5. Gotchas
* **Mixed Container Abstractions:** The class uses `IContainerRegistry` (Prism abstraction) in `RegisterTypes`, but immediately delegates to the `IUnityContainer` (Unity specific) stored in a field to perform the actual registration. This bypasses Prism's container abstraction, making the module tightly coupled to Unity and potentially ignoring the `containerRegistry` parameter passed to `RegisterTypes`.
* **Side Effects in Property Getters:** In `TestModificationModuleImageAttribute`, the `AssemblyImage` property getter performs a file/resource load operation (`AssemblyInfo.GetImage(...)`) and overwrites the private `_img` field every time it is accessed. This is inefficient and violates standard property getter expectations of low cost and idempotency.
* **Unused Constructor Parameters:** The constructors for `TestModificationModuleNameAttribute(string s)` and `TestModificationModuleImageAttribute(string s)` accept a string parameter `s` that is never used in the method body.
* **Redundant Method:** The `Initialize()` method is public but appears to be legacy code or a specific pattern choice, as `RegisterTypes` is the standard Prism location for type registration. The separation serves no functional purpose given `RegisterTypes` immediately calls it.

View File

@@ -0,0 +1,196 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/Enums.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/TestModificationModel.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Model/TestModelManipulation.cs
generated_at: "2026-04-16T13:47:44.691721+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "1e3214665d63bf12"
---
# Test Modification Module Documentation
## 1. Purpose
This module provides functionality for modifying test data within the DTS Viewer application. It manages the state of user-initiated modifications to channel parameters (sensitivity, EU offset/multiplier, T0 timing, line fit, software filters, data flags, and descriptions), tracks which values have been modified from their originals, and handles the persistence of these changes to both `.dts` XML files and binary `.chn` channel files. The module also manages backup/restore operations to allow undoing modifications.
---
## 2. Public Interface
### Enums.cs
#### `Keys` Enum
```csharp
public enum Keys
{
ApplyShiftT0ModsTestOnly // System Setting for whether to restrict "Shift T0" test modifications to "Test" only.
}
```
- Defines configuration keys used by the TestModification module.
---
### TestModificationModel.cs
#### `TestModificationModel` Class
Implements `ITestModificationModel`. A model class that tracks modification state for a selected test channel.
**Calibration Properties:**
- `string CalDate` — Read-only; returns calibration date or empty string if `Cal` is null.
- `string ModifyDate` — Read-only; returns modify date/time or empty string if `Cal` is null.
- `double CalSensitivity` — Gets/sets sensitivity from the first calibration record; returns `double.NaN` if unavailable.
- `bool ProportionalToExcitation` — Read-only; returns whether calibration is proportional to excitation.
- `bool ShowSensorCal` — Read-only; returns true if `Cal` and `Sensor` exist and calibration is not non-linear.
- `bool NonLinear` — Read-only; returns whether calibration is non-linear.
- `ISensorCalDbRecord Cal` — Gets/sets the latest calibration record for the channel.
- `ISensorDbRecord Sensor` — Gets/sets the sensor corresponding to the channel.
**Selection & Description:**
- `ITestChannel SelectedChannel` — The currently selected test channel.
- `string Description` — Channel description string.
- `bool IsModifiedDescription` — True if description differs from `SelectedChannel.ChannelDescriptionString`.
**EU (Engineering Units) Properties:**
- `double EuMultiplier` — EU multiplier value.
- `bool IsModifiedEuMultiplier` — True if multiplier differs from `SelectedChannel.Multiplier`.
- `double EuOffset` — EU offset value.
- `bool IsModifiedEuOffset` — True if offset differs from `SelectedChannel.UserOffsetEu`.
**Timing Properties:**
- `double T0` — T0 shift value (milliseconds).
- `bool IsModifiedT0` — True if T0 is not equal to 0.
- `T0Mode T0Mode` — Indicates whether T0 changes apply to DAS or Test; coerced to `T0Mode.Test` if `IsT0ModeTestOnly` is true.
- `bool IsT0ModeTestOnly` — Internal setter; restricts T0 mode selection.
**Line Fit Properties:**
- `double T1` — Line fit start point (milliseconds).
- `double T2` — Line fit end point (milliseconds).
- `bool IsModifiedLineFit` — True if T1 or T2 are non-zero.
**Sensitivity & Filter:**
- `double Sensitivity` — Channel sensitivity value.
- `bool IsModifiedSensitivity` — True if sensitivity differs from `SelectedChannel.Sensitivity`.
- `IFilterClass SelectedFilter` — Selected software filter; defaults to `FilterClass(FilterClassType.Unfiltered)`.
- `bool IsModifiedFilter` — True if filter differs from `SelectedChannel.SoftwareFilter`.
**Data Flag:**
- `DataFlag SelectedDataFlag` — Selected data flag; defaults to `DataFlag.None`.
- `bool IsModifiedDataFlag` — True if data flag differs from `SelectedChannel.DataFlag`.
**Control Enable Properties (internal setters):**
- `bool EnableSensitivityControl`
- `bool EnableLineFitControl`
- `bool EnableEUOffsetControl`
- `bool EnableEUMultiplierControl`
- `bool EnableFilterControl`
- `bool EnableDescriptionControl`
- `bool IsDataFlagEnabled`
- `bool IsT0Enabled`
**State Tracking:**
- `bool IsModified` — True if any modification flag is true and `SelectedChannel` is not null.
- `bool IsSaved` — Read-only property (appears unimplemented in source).
- `ITestModificationViewModel Parent` — Reference to parent view model.
**Methods:**
- `void OnPropertyChanged(string propertyName)` — Raises `PropertyChanged` event and recalculates `IsModified`.
- `bool ValidateT0()` — Validates that T0 falls within the dataset's start and end time bounds.
**Commands:**
- `DelegateCommand UpdateDatabaseCommand` — Executes `Parent.UpdateDatabaseMethod()`.
---
### TestModelManipulation.cs
#### `TestModelManipulation` Class
Static utility class for file-based test modification operations.
**Constants:**
```csharp
public const double UNUSED_START_TIME = 0;
public const int UNUSED_DATA_COLLECTION_LENGTH = 0;
private const string BackupHeaderExtension = ".header.bak";
private const string BackupFileExtension = ".bak";
```
**Public Methods:**
- `static void UndoAllModification(ITestModificationModel model)` — Reverts all modifications by restoring `.dts` and all binary `.chn` files from backups. Publishes `TestModificationEvent` and optionally `ChannelsModificationNotification`/`RefreshTestRequestEvent`.
- `static bool BackupExists(ITestModificationModel model)` — Returns true if a `.dts.bak` or `.chn.bak` file exists for the selected channel.
- `static bool SaveModification(ITestModificationModel model, bool useISOCodeFilterMapping, bool bUseZeroForUnfiltered)` — Persists all modifications to disk. Handles T0 (Test or DAS mode), line fit, sensitivity, filter, EU offset/multiplier, description, and data flag changes. Returns true on success.
- `static bool SaveModificationDataFlag(ITestModificationModel model)` — Saves only data flag modifications to the `.dts` file.
- `static void ApplyLineFit(ITestModificationModel model, Test.Module.Channel channel)` — Applies a linear interpolation between T1 and T2 sample indices, modifying the channel's ADC data in place.
- `static void PreviewLineFit(ITestModificationModel model)` — Publishes `ChannelsModificationLineFitNotification` with line fit parameters for UI preview without disk modification.
- `static void UndoModification(ITestModificationModel model)` — Reverts in-memory model state from the selected channel and publishes `ChannelsModificationNotification`.
- `static void PopulateFromChannel(ITestModificationModel model)` — Initializes model properties from `SelectedChannel` values.
- `static void BackupChannelIfNeeded(Test.Module.Channel testModuleChannel, bool headerOnly)` — Creates a backup of a `.chn` file (full file or header only).
---
## 3. Invariants
1. **IsModified Consistency**: `IsModified` is always `false` when `SelectedChannel` is `null`, regardless of other property states.
2. **T0Mode Coercion**: When `IsT0ModeTestOnly` is `true`, the `T0Mode` setter always coerces the value to `T0Mode.Test`.
3. **Backup File Semantics**: Backup files (`.bak` and `.header.bak`) represent the *original* unmodified state. If a backup already exists, it is not overwritten—this preserves the original file for undo operations.
4. **Line Fit Index Ordering**: In `ApplyLineFit`, if `startIndex > endIndex`, the values are swapped before processing.
5. **Calibration Record Access**: `CalSensitivity` always accesses `Cal.Records.Records[0]` (first record); behavior is undefined if multiple records exist and others are relevant.
6. **T0 Validation Bounds**: `ValidateT0()` returns `true` (valid) if `SelectedChannel` or `SelectedChannel.ParentModule` is null, treating unavailable data as "no constraint."
---
## 4. Dependencies
**This module depends on:**
- `DTS.Common` — Core utilities and interfaces
- `DTS.Common.Classes.Sensors` — Sensor-related classes
- `DTS.Common.Enums.Sensors` — Sensor enumerations including `DataFlag`, `T0Mode`
- `DTS.Common.Interface` — Core interfaces including `ITestChannel`
- `DTS.Common.Interface.Sensors` — Sensor interfaces including `ISensorCalDbRecord`, `ISensorDbRecord`
- `DTS.Common.Interface.Sensors.SoftwareFilters``IFilterClass`, `FilterClass`, `FilterClassType`
- `DTS.Common.Events` — Event types (`TestModificationEvent`, `TestModificationArgs`, `ChannelsModificationNotification`, `ChannelsModificationLineFitNotification`, `LineFitArgs`, `RefreshTestRequestEvent`)
- `DTS.Common.Settings``SettingsDB` for global settings
- `DTS.Common.Utilities.Logging``APILogger`
- `DTS.Serialization` — Serialization utilities for `.chn` and `.dts` files
- `DTS.SensorDB` — Sensor database interfaces
- `Prism.Commands``DelegateCommand`
- `Prism.Ioc``ContainerLocator`
- `Prism.Events``IEventAggregator`
**Consumers of this module:**
- Not explicitly shown in source; inferred consumer is `ITestModificationViewModel` implementation referenced via `Parent` property.
---
## 5. Gotchas
1. **Namespace Mismatch**: `TestModificationModel.cs` declares namespace `DTS.Viewer.ChartOptions.Model` while the file path suggests `DTS.Viewer.TestModification.Model`. This inconsistency may cause confusion or require external namespace mapping.
2. **IsSaved Property Unimplemented**: The `IsSaved` property has a getter but no setter or backing field initialization, meaning it will always return `false` (default for `bool`).
3. **T0 DAS Mode Scope**: When `T0Mode.DAS` is used, T0 changes are applied to all modules matching the `BaseSerialNumber` of the module containing the selected channel—even if those modules don't contain the selected channel itself. This is a cross-module modification.
4. **Line Fit Boundary Handling**: `ApplyLineFit` uses indices `startIndex + 1` through `endIndex - 1` for interpolation, meaning the actual start and end points are not modified (they define the line but are not overwritten).
5. **File Encoding Assumption**: `WriteDTSFileChanges` forces UTF-16 encoding with a fallback to default encoding on exception. The comment indicates this is intentional for `.dts` file compatibility.
6. **Thread.Sleep in File Write**: `WriteDTSFileChanges` includes `System.Threading.Thread.Sleep(10)` after writing—purpose is unclear from source alone, possibly a workaround for file locking or timing issues.
7. **ISO Code Filter Mapping Side Effect**: When `useISOCodeFilterMapping` is true in `SaveModification`, modifying the filter also modifies the channel's `IsoCode` field, which triggers a header backup even if only the filter was changed.
8. **BackupExists Returns True for Any Backup**: The method returns `true` if either `.dts.bak` or `.chn.bak` exists, not necessarily both. This could indicate partial backup state.

View File

@@ -0,0 +1,46 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:46:59.533949+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "159c8c375f9a8da3"
---
# Documentation: DTS.Viewer.TestModification Assembly Configuration
## 1. Purpose
This file provides assembly-level metadata attributes for the `DTS.Viewer.TestModification` module. It configures the embedded manifest for the compiled .NET assembly, defining its identity, version, copyright information, and COM visibility settings. It exists to satisfy .NET build requirements for assembly information, particularly in older project formats or when explicit assembly info generation is required.
## 2. Public Interface
This file does not expose any classes, methods, or functions for programmatic invocation. It strictly uses assembly-level attributes to configure the compiled binary. The defined attributes are:
* **`AssemblyTitle`**: Set to `"DTS.Viewer.TestModification"`.
* **`AssemblyDescription`**: Set to an empty string.
* **`AssemblyConfiguration`**: Set to an empty string.
* **`AssemblyCompany`**: Set to an empty string.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.TestModification"`.
* **`AssemblyCopyright`**: Set to `"Copyright © 2017"`.
* **`AssemblyTrademark`**: Set to an empty string.
* **`AssemblyCulture`**: Set to an empty string (indicates the assembly is culture-neutral).
* **`ComVisible`**: Set to `false`. Prevents types within the assembly from being visible to COM components.
* **`Guid`**: Set to `"5ee7c61f-e9fe-479b-be1f-78a142341c3b"`. Acts as the ID for the type library if the assembly is exposed to COM.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`. Defines the version used by the common language runtime.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`. Defines the version stored in the file's Win32 file version resource.
## 3. Invariants
* **COM Visibility:** The attribute `[assembly: ComVisible(false)]` ensures that no types in this assembly are exposed to COM by default. To expose a specific type, this attribute would need to be overridden at the class level.
* **Versioning:** Both the assembly version and file version are explicitly fixed at `1.0.0.0`. They will not auto-increment with builds unless the file is manually updated or the build process modifies it externally.
* **Culture:** The assembly is strictly culture-neutral (`AssemblyCulture("")`), implying it does not contain satellite resources for a specific language.
## 4. Dependencies
* **Internal Dependencies:**
* `System.Reflection`: Required for the assembly attributes.
* `System.Runtime.CompilerServices`: Required for assembly attributes.
* `System.Runtime.InteropServices`: Required for the `Guid` and `ComVisible` attributes.
* **External Dependencies:** None inferred from this file alone. This file is a configuration artifact consumed by the compiler during the build of the `DTS.Viewer.TestModification` project.
## 5. Gotchas
* **Empty Metadata:** Several informational attributes (`AssemblyDescription`, `AssemblyCompany`, `AssemblyConfiguration`) are initialized as empty strings. This may result in sparse metadata when inspecting the compiled DLL properties in Windows Explorer.
* **Legacy Project Format:** The presence of an explicit `AssemblyInfo.cs` with commented-out wildcard versioning syntax (`// [assembly: AssemblyVersion("1.0.*")]`) suggests this project uses a legacy (non-SDK style) .NET project format. Modern .NET Core/5+ projects typically auto-generate this information in the `.csproj` file, which can lead to build conflicts (CS0579 duplicate attribute errors) if this file is left in a modern project without disabling auto-generation.
* **Hardcoded Version:** The version numbers are hardcoded. If continuous integration relies on auto-incrementing build numbers, this file would need to be modified by the build server or replaced with wildcard syntax.

View File

@@ -0,0 +1,117 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:46:55.298377+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "46010437bced3eec"
---
# Documentation: DTS.Viewer.TestModification.Resources
## 1. Purpose
This module provides localization support for the DTS Viewer Test Modification feature. It enables XAML-based string resource lookup through a WPF markup extension (`TranslateExtension`) backed by a strongly-typed, auto-generated resource class (`StringResources`). The module centralizes all user-facing strings for the test modification UI, supporting potential internationalization and ensuring consistent string management.
---
## 2. Public Interface
### TranslateExtension (public class)
**Namespace:** `DTS.Viewer.TestModification`
**Base Class:** `System.Windows.Markup.MarkupExtension`
**Attribute:** `[MarkupExtensionReturnType(typeof(string))]`
A WPF markup extension that enables XAML bindings to localized string resources.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `TranslateExtension(string key)` | Initializes the extension with the resource key to look up. The key is stored in a readonly field `_key`. |
| Method | `public override object ProvideValue(IServiceProvider serviceProvider)` | Returns the localized string for the provided key via `StringResources.ResourceManager.GetString(_key)`. Returns `#stringnotfound#` if key is null/empty, or `#stringnotfound# {key}` if the key is not found in resources. |
**Constants:**
- `private const string NotFound = "#stringnotfound#"` — Fallback value returned when a resource key is invalid or missing.
---
### StringResources (internal class)
**Namespace:** `DTS.Viewer.TestModification.Resources`
**Attributes:** `[GeneratedCode]`, `[DebuggerNonUserCode]`, `[CompilerGenerated]`
An auto-generated strongly-typed resource class. **Do not modify manually** — edits will be lost on regeneration.
| Member | Signature | Description |
|--------|-----------|-------------|
| Property | `internal static ResourceManager ResourceManager` | Returns the cached `ResourceManager` instance for the resource bundle `"DTS.Viewer.TestModification.Resources.StringResources"`. Lazily initialized. |
| Property | `internal static CultureInfo Culture` | Gets or sets the `CultureInfo` used for resource lookups. Overrides `CurrentUICulture` for this resource class. |
**Localized String Properties (all `internal static string`):**
| Property | Default Value (from comments) |
|----------|-------------------------------|
| `CalDate` | "Cal date" |
| `DataFlag` | "Data Flag:" |
| `Description` | "Description:" |
| `EUMultiplier` | "EU Multiplier:" |
| `EUOffset` | "EU Offset:" |
| `FailedToModifySensitivity` | "Failed to modify sensitivity: " |
| `Filter` | "Filter:" |
| `LineFit` | "Line Fit:" |
| `ModifyDate` | "Modify date" |
| `NonLinear` | "Non-linear" |
| `PleaseLockHeader` | "To enable, please lock a single channel." |
| `Preview` | "Preview" |
| `ProportionalToExcitation` | "Proportional to excitation" |
| `Sensitivity` | "Sensitivity:" |
| `SensorCalibration` | "Sensor calibration (most recent in db)" |
| `ShiftT0ms` | "Shift T₀ (ms):" |
| `T0MustBeInDataset` | "Modification can not be made, T0 must be in the dataset." |
| `T1ms` | "T₁ (ms):" |
| `T2ms` | "T₂ (ms):" |
| `Undo` | "Cancel" |
| `UndoAll` | "Restore All" |
| `UndoAllPrompt` | "This will revert your saved test modifications to the backup on file. Continue?" |
| `UndoPrompt` | "This will undo any change(s) to this channel made before saving. Continue?" |
| `UpdateDatabase` | "Update database" |
| `WriteFiles` | "Write" |
| `WriteFilesPrompt` | "Are you sure you want to write these changes to disk?" |
---
## 3. Invariants
1. **Key immutability:** The `_key` field in `TranslateExtension` is readonly and set only at construction time.
2. **Fallback behavior:** `ProvideValue` will never return null — it always returns either a valid localized string or a string containing `#stringnotfound#`.
3. **Error differentiation:** A null/empty key returns `"#stringnotfound#"` alone; a missing key returns `"#stringnotfound# {key}"` (includes the key name).
4. **Resource manager singleton:** `StringResources.ResourceManager` is lazily initialized and cached; subsequent accesses return the same instance.
5. **Auto-generated code:** `StringResources.Designer.cs` is regenerated by tooling; manual changes will be overwritten.
---
## 4. Dependencies
### This module depends on:
- `System` — Core .NET types
- `System.Windows.Markup``MarkupExtension` base class for XAML support
- `System.Resources``ResourceManager` for resource lookup
- `System.Globalization``CultureInfo` for localization
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices` — Attributes for auto-generated code
### What depends on this module:
- XAML files in `DTS.Viewer.TestModification` that use the `{x:Static}` or `{local:Translate}` markup extension pattern for localized UI strings
- Code-behind in the TestModification module that accesses `StringResources` properties directly
---
## 5. Gotchas
1. **Different error formats:** A null/empty key returns `"#stringnotfound#"` without the key name, while a valid-but-missing key returns `"#stringnotfound# {key}"`. This could cause confusion when debugging missing resources.
2. **Auto-generated file:** `StringResources.Designer.cs` is tool-generated. To add or modify strings, edit the `.resx` file, not this file. The comments explicitly warn: "Changes to this file may cause incorrect behavior and will be lost if the code is regenerated."
3. **Internal visibility:** `StringResources` is `internal`, limiting access to within the assembly. `TranslateExtension` is `public`, making it usable from XAML regardless of assembly boundaries.
4. **Culture management:** The `Culture` property on `StringResources` allows overriding the lookup culture, but this is a global setting for the class. If set, it affects all subsequent resource lookups through this class. It is unclear from source alone whether/how the application manages this property at runtime.

View File

@@ -0,0 +1,72 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/View/TestModificationView.xaml.cs
generated_at: "2026-04-16T13:47:19.361025+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "3165a969f0d942bf"
---
# Documentation: TestModificationView.xaml.cs
## 1. Purpose
This module provides the code-behind for a WPF view component (`TestModificationView`) within the DTS Viewer application's TestModification module. It implements the `ITestModificationView` interface and exposes available filter class options to the view layer, serving as a bridge between the sensor database configuration and the UI for test modification functionality.
---
## 2. Public Interface
### `TestModificationView` (Class)
**Implements:** `ITestModificationView`
#### Constructor
```csharp
public TestModificationView()
```
Initializes the view component by calling `InitializeComponent()`, which loads the associated XAML.
#### Property: `AvailableCFC`
```csharp
public List<IFilterClass> AvailableCFC { get; }
```
Returns a list of available filter classes (CFC = Channel Filter Classes, per comment "FB 13120"). Each access instantiates a new `AnalogSettingDefaults` object and returns its `FilterOptions` property.
---
## 3. Invariants
- The `AvailableCFC` property always returns a non-null `List<IFilterClass>` (the actual nullability depends on `AnalogSettingDefaults.FilterOptions` implementation, which is external to this file).
- The view is a partial class; the XAML counterpart (`TestModificationView.xaml`) must exist for `InitializeComponent()` to succeed.
- The class implements `ITestModificationView`, implying contractual obligations defined in that interface (not visible in this source).
---
## 4. Dependencies
### This module depends on:
- `DTS.Common.Interface` — provides `ITestModificationView` interface
- `DTS.Common.Interface.Sensors.SoftwareFilters` — provides `IFilterClass` interface
- `DTS.SensorDB` — provides `AnalogSettingDefaults` class
- `System.Windows.Controls` — WPF infrastructure (UserControl base, implied by `InitializeComponent()` pattern)
### Unused import:
- `System.Text.RegularExpressions` — imported but not referenced in this file
### What depends on this module:
- Cannot be determined from this source file alone (likely referenced by a module registration/bootstrapper or a parent view).
---
## 5. Gotchas
1. **Object allocation on every property access**: The `AvailableCFC` getter creates a new `AnalogSettingDefaults` instance on every call. If this property is data-bound and accessed frequently by WPF, it could cause unnecessary allocations. Consider whether caching is appropriate.
2. **Unused import**: `System.Text.RegularExpressions` is imported but not used in this file. This may indicate dead code, a missing implementation, or usage in the XAML portion.
3. **Namespace suppression**: The file includes `// ReSharper disable CheckNamespace`, suggesting the namespace may not match the folder structure. This could cause confusion when navigating the codebase.
4. **FB 13120 reference**: The comment references a tracking item (likely a bug or feature request). The context and resolution status of this item are unknown from the source alone.

View File

@@ -0,0 +1,135 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestModification/ViewModel/TestModificationViewModel.cs
generated_at: "2026-04-16T13:45:56.000728+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "297454e79e1ccbbd"
---
# Documentation: TestModificationViewModel
## 1. Purpose
`TestModificationViewModel` is a Prism-based ViewModel that manages the test modification UI panel in the DTS Viewer application. It enables users to modify test data properties (T0 timing, sensitivity, line fit, descriptions, EU multipliers/offsets, filters, and data flags) for selected channels. The class coordinates between the UI, a sensor calibration database, and the broader application via event aggregation, while enforcing permission-based edit controls and providing undo/redo capabilities for modifications.
---
## 2. Public Interface
### Constructor
```csharp
public TestModificationViewModel(
ITestModificationView view,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the ViewModel, sets up the View's DataContext, creates interaction requests, and subscribes to four events: `RaiseNotification`, `GraphSelectedChannelsNotification`, `ShiftT0Event`, and `SetUseZeroForUnfilteredEvent`.
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `ITestModificationView` | Gets/sets the associated view instance. |
| `Parent` | `IBaseViewModel` | Gets/sets the parent ViewModel reference. |
| `Model` | `TestModificationModel` | The model containing channel modification state. Setting updates the model's `Parent` reference. |
| `PreviewCommand` | `DelegateCommand` | Executes `PreviewMethod()` to preview line fit changes. |
| `WriteCommand` | `DelegateCommand` | Executes `WriteMethod()` to persist modifications after validation and user confirmation. |
| `UndoCommand` | `DelegateCommand` | Executes `UndoMethod()` to revert the last modification. |
| `UndoAllCommand` | `DelegateCommand` | Executes `UndoAllMethod()` to revert all modifications. |
| `TestModificationVisability` | `bool` | Controls visibility of the modification panel; true only when exactly one channel is selected. |
| `IsBackedUp` | `bool` | Indicates whether a backup exists for the current model state. Private setter. |
| `UseISOCodeFilterMapping` | `bool` | When true, forces ISOCode field filter to match channel's SoftwareFilter. Defaults to `false`. |
| `UseZeroForUnfiltered` | `bool` | Gets/sets whether to use zero for unfiltered values. Set via `SetUseZeroForUnfilteredEvent`. |
| `IsFilterEnabled` | `bool` | Gets/sets filter enabled state with property change notification. |
| `HeaderInfo` | `string` | Returns `"TestSummaryRegion"`. |
| `IsBusy` | `bool` | Busy indicator with property change notification. |
| `IsDirty` | `bool` | Dirty state flag. |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for confirmations. |
### Methods
```csharp
public void UpdateDatabaseMethod()
```
Updates calibration in the database. Sets `CalibrationId = -1`, updates `ModifyDate` to `DateTime.Now`, creates a new `SensorCalibration`, inserts via `DbOperations.SensorCalibrationsInsert()`, then refreshes `Model.Cal` from latest database record. Publishes `PageErrorEvent` on failure.
```csharp
public override void Initialize()
```
Empty override.
```csharp
public override void Initialize(object parameter)
```
Sets `Parent` to the provided parameter cast as `IBaseViewModel`.
```csharp
public void PublishChanges()
```
If not populating and `Model.IsModifiedDataFlag` is true, immediately saves the data flag modification and updates `IsBackedUp`. Always publishes `TestModificationChangedEvent` with the current model.
---
## 3. Invariants
1. **Single-Channel Selection**: `TestModificationVisability` is `true` only when `channels.Count == 1 && channels.Count(x => x.IsSelected) == 1`. Multi-channel or no selection disables the modification panel.
2. **T0 Validation**: T0 shifts are validated via `Model.ValidateT0()` before write operations. T0 cannot shift beyond the dataset bounds (addresses case #14661).
3. **Calibration Sorting**: Calibration records are sorted in ascending order by `CalibrationDate`, then by `ModifyDate` as a tiebreaker (see `CompareCalibrations`).
4. **Analog Sensor Calibration Display**: Calibrations are only displayed for sensors where `SensorType == 0` (analog sensors).
5. **Permission-Based Controls**: Edit permissions (`EnableSensitivityControl`, `EnableLineFitControl`, `EnableDescriptionControl`, `EnableEUMultiplierControl`, `EnableEUOffsetControl`, `EnableFilterControl`, `IsT0Enabled`, `IsDataFlagEnabled`) are gated by `IViewerMainViewModel.DoesUserHaveEditPermission`.
6. **Population Guard**: The static `IsPopulating` flag prevents `PublishChanges()` from executing data flag saves during model population.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Base` (`BaseViewModel<T>`)
- `DTS.Common.Events` (`PageErrorEvent`, `PageErrorArg`, `ShiftT0Event`, `ShiftT0EventArguments`, `TestModificationChangedEvent`, `ShowT0CursorEvent`, `GraphSelectedChannelsNotification`, `GraphSelectedChannelsNotificationArg`, `RaiseNotification`, `SetUseZeroForUnfilteredEvent`)
- `DTS.Common.Interactivity` (`Notification`, `Confirmation`, `NotificationContentEventArgs`, `InteractionRequest<T>`)
- `DTS.Common.Interface` (`IBaseViewModel`, `IViewerMainViewModel`)
- `DTS.Common.Interface.Sensors` (`ISensorDbRecord`, `ISensorCalDbRecord`)
- `DTS.Common.Settings` (`SettingsDB`, `Keys`)
- `DTS.Common.Storage` (implied via `DbOperations`)
- `DTS.Common.Utilities.Logging` (`APILogger`)
- `DTS.SensorDB` (`DbOperations`, `SensorCalibration`)
- `DTS.Viewer.ChartOptions.Model` (channel types)
- `DTS.Viewer.TestModification.Model` (`TestModificationModel`, `TestModelManipulation`)
- `Prism.Commands` (`DelegateCommand`)
- `Prism.Events` (`IEventAggregator`)
- `Prism.Regions` (`IRegionManager`)
- `Unity` (`IUnityContainer`)
### What Depends On This Module:
- `ITestModificationView` (the associated View)
- `ITestModificationViewModel` (interface consumers)
- Event subscribers to `TestModificationChangedEvent`
---
## 5. Gotchas
1. **Typo in Property Name**: `TestModificationVisability` is misspelled (should be "Visibility"). This is a historical naming quirk.
2. **Silent Exception Swallowing**: `GetLatestCalibration()` catches all exceptions and returns `null` without logging. The comment explicitly states: "there's no access to APILogger here, so rather than adding a reference, just eat the error."
3. **Malformed XML Comment**: The `<summary>` tag for `GetLatestCalibration` is not properly closed (uses `<summary>` instead of `</summary>`).
4. **Base Member Hiding**: Multiple properties (`Model`, `IsBusy`, `IsDirty`, `IsNavigationIncluded`, `PropertyChanged`, `OnPropertyChanged`) use the `new` keyword to hide base class members, which may indicate design issues or legacy refactoring.
5. **Static `IsPopulating` Flag**: The `IsPopulating` property is static, meaning it is shared across all instances of `TestModificationViewModel`. This could cause unexpected behavior if multiple instances exist.
6. **Hardcoded CalibrationId**: `UpdateDatabaseMethod()` sets `CalibrationId = -1` before insertion. The significance of `-1` is not documented in source.
7. **Database Setting Fallback**: `UseISOCodeFilterMapping` defaults to `false` but is retrieved from settings in `WriteMethod()` with a default of `true` via `SettingsDB.GetGlobalValueBool("UseISOCodeFilterMapping", true)`. The property default and settings default are inconsistent.
8. **Null Check Inconsistency**: Some null checks use `null == sensor` style while others use `sensor == null` (likely ReSharper-generated variations).

View File

@@ -0,0 +1,72 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/TestSummaryListModule.cs
generated_at: "2026-04-16T13:44:28.584729+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b68514768022da67"
---
# Documentation: TestSummaryListModule
## 1. Purpose
This module serves as the entry point for the "Test Summary List" component within the DTS Viewer application. It is a Prism module responsible for self-registering its View (`TestSummaryListView`) and ViewModel (`TestSummaryViewListModel`) with the Unity dependency injection container. Additionally, it defines assembly-level metadata attributes to expose the module's name, icon, grouping, and target region to the main application shell.
## 2. Public Interface
### Classes
**`TestSummaryListModule`**
Implements `Prism.Modularity.IModule`.
* `TestSummaryListModule(IUnityContainer unityContainer)`: Constructor that accepts an `IUnityContainer` instance via dependency injection.
* `RegisterTypes(IContainerRegistry containerRegistry)`: Implements the `IModule` interface. It invokes the `Initialize()` method to register the module's types.
* `OnInitialized(IContainerProvider containerProvider)`: Implements the `IModule` interface. Currently contains no implementation logic.
* `Initialize()`: Registers `ITestSummaryListView` to `TestSummaryListView` and `ITestSummaryListViewModel` to `TestSummaryViewListModel` using the `_unityContainer`.
**`TestSummaryListModuleNameAttribute`**
Inherits from `DTS.Common.Interface.TextAttribute`.
* `TestSummaryListModuleNameAttribute()`: Default constructor.
* `TestSummaryListModuleNameAttribute(string s)`: Overloaded constructor (parameter `s` is unused).
* `AssemblyName` (Property): Returns `AssemblyNames.TestSummaryList.ToString()`.
* `GetAttributeType()`: Returns `typeof(TextAttribute)`.
* `GetAssemblyName()`: Returns the `AssemblyName` property value.
**`TestSummaryListModuleImageAttribute`**
Inherits from `DTS.Common.Interface.ImageAttribute`.
* `TestSummaryListModuleImageAttribute()`: Default constructor.
* `TestSummaryListModuleImageAttribute(string s)`: Overloaded constructor (parameter `s` is unused).
* `AssemblyImage` (Property): Gets a `BitmapImage` by calling `AssemblyInfo.GetImage` with `AssemblyNames.TestSummaryList.ToString()`.
* `AssemblyName` (Property): Returns `AssemblyNames.TestSummaryList.ToString()`.
* `AssemblyGroup` (Property): Returns `eAssemblyGroups.Viewer.ToString()`.
* `AssemblyRegion` (Property): Returns `eAssemblyRegion.TestSummaryRegion`.
* `GetAttributeType()`: Returns `typeof(ImageAttribute)`.
* `GetAssemblyImage()`: Returns the `AssemblyImage` property value.
* `GetAssemblyName()`: Returns the `AssemblyName` property value.
* `GetAssemblyGroup()`: Returns the `AssemblyGroup` property value.
* `GetAssemblyRegion()`: Returns the `AssemblyRegion` property value.
## 3. Invariants
* **Module Name:** The module is identified by the string "TestSummaryList" in the `[Module]` attribute.
* **Registration Mapping:** The `Initialize` method strictly maps `ITestSummaryListView` to the concrete class `TestSummaryListView` and `ITestSummaryListViewModel` to the concrete class `TestSummaryViewListModel`.
* **Assembly Region:** The module is hardcoded to target `eAssemblyRegion.TestSummaryRegion`.
* **Assembly Group:** The module is hardcoded to belong to `eAssemblyGroups.Viewer`.
## 4. Dependencies
**Internal Dependencies (Inferred from imports and usage):**
* `DTS.Common`: Uses `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, and `AssemblyInfo`.
* `DTS.Common.Interface`: Uses `TextAttribute`, `ImageAttribute`.
* `DTS.Viewer.TestSummaryList.ViewModel`: Uses `ITestSummaryListViewModel` and `TestSummaryViewListModel`.
* `DTS.Viewer.TestSummaryList` (Local Namespace): Uses `TestSummaryListView` and `ITestSummaryListView` (interfaces/views expected to be present in this namespace).
**External Framework Dependencies:**
* `Prism.Ioc`: Uses `IContainerProvider`, `IContainerRegistry`.
* `Prism.Modularity`: Uses `IModule`, `ModuleAttribute`.
* `Unity`: Uses `IUnityContainer`.
* `System.Windows.Media.Imaging`: Uses `BitmapImage`.
## 5. Gotchas
* **Mixed Container Usage:** The `RegisterTypes` method receives an `IContainerRegistry` (Prism abstraction) but ignores it. Instead, it calls `Initialize()`, which uses the injected `IUnityContainer` directly. This bypasses the Prism container abstraction, making the module tightly coupled to Unity rather than being container-agnostic.
* **Unused Constructor Parameters:** Both attribute classes (`TestSummaryListModuleNameAttribute` and `TestSummaryListModuleImageAttribute`) have constructors accepting a `string s` that is never used in the logic.
* **ViewModel Naming Inconsistency:** The source registers `ITestSummaryListViewModel` to `TestSummaryViewListModel`. The concrete class name appears to be missing an 'e' ("ViewLabel" vs "ViewModel"), which may be a typo or a specific naming convention in the codebase.
* **Getter Side Effects:** The `AssemblyImage` property getter in `TestSummaryListModuleImageAttribute` modifies the private field `_img` before returning it. This is a side effect in a getter, which is generally unexpected and could cause issues if the property is accessed frequently or by multiple threads (though `BitmapImage` initialization likely mitigates repeated work, the pattern is non-standard).

View File

@@ -0,0 +1,103 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/Model/TestSummaryModel.cs
generated_at: "2026-04-16T13:55:21.942566+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "eacbbab8741bd493"
---
# Documentation: TestSummaryModel.cs
## 1. Purpose
`TestSummaryModel` is a model class within the `DTS.Viewer.TestSummaryList` module responsible for loading and managing test summary data from `.dts` files. It implements `IBaseModel` and serves as the data access layer between the file system and the `ITestSummaryListViewModel`, handling asynchronous test metadata retrieval, list merging logic, and test selection state management. The class coordinates UI busy states and publishes application-wide events via Prism's `IEventAggregator`.
---
## 2. Public Interface
### Properties
| Name | Type | Description |
|------|------|-------------|
| `Parent` | `ITestSummaryListViewModel` | Reference to the parent ViewModel. Settable property. |
| `_eventAggregator` | `IEventAggregator` | Prism event aggregator for publishing/subscribing to application events. Settable property. |
| `IsSaved` | `bool` | Get-only property. **Note:** Appears unassigned in source (ReSharper suppression present). |
| `PropertyChanged` | `PropertyChangedEventHandler` | Event raised when a property value changes. |
### Methods
#### `void GetTestSummary(string path, string file, bool Include = false, bool selectAll = false)`
Loads test definitions from the specified data folder asynchronously.
- **Parameters:**
- `path` - Directory path to the data folder. Will be created if it doesn't exist.
- `file` - The `.dts` file to load.
- `Include` - When `true` and list has multiple items, selects the first test in the list.
- `selectAll` - When `true`, selects all tests; otherwise uses default selection logic.
- **Behavior:**
- Sets `Parent.IsBusy = true` and publishes `BusyIndicatorChangeNotification(true)`.
- Publishes `AppStatusExEvent` with `AppStatusArg.Busy`.
- Creates the directory at `path` if it doesn't exist.
- Delegates to `TestMetadataList.GetTestSummaryListAsync()` to retrieve test summaries.
- Merges results into `Parent.TestSummaryList`, preserving existing selection state for duplicate tests.
- Calls `DetermineTestsSelected(selectAll)` to apply selection logic.
- Publishes `TestLoadedCountNotification` with loaded count and parent ViewModel reference.
- Publishes `BusyIndicatorChangeNotification(false)` and sets `Parent.IsBusy = false` on completion.
#### `void OnPropertyChanged(string propertyName)`
Raises the `PropertyChanged` event for the specified property name.
---
## 3. Invariants
1. **Directory Creation:** If `path` is non-empty and the directory doesn't exist, it will be created before loading tests.
2. **Test Uniqueness:** Tests are uniquely identified by the combination of `Id`, `SetupName`, and `DataType`. When a duplicate is detected, the existing test is replaced at its original index while preserving its `IsSelected` state.
3. **Selection Guarantees:**
- If `selectAll` is `true`, all tests in `Parent.TestSummaryList` will have `IsSelected = true`.
- If `selectAll` is `false` and the list contains exactly one test, that test is selected.
- If `selectAll` is `false`, the list has multiple tests, and all tests share the same setup name with at least one `DataType == "ALL"`, the first test is selected.
4. **Event Pairing:** `BusyIndicatorChangeNotification` and `AppStatusExEvent` are always published in pairs (busy/available) even in exception scenarios via the `finally` block.
---
## 4. Dependencies
### This Module Depends On:
- `DTS.Common.Classes.Viewer.TestMetadata.TestMetadataList` - Provides `GetTestSummaryListAsync()` method.
- `DTS.Common.Base.IBaseModel` - Interface implemented by this class.
- `DTS.Common.Events` - Event types: `BusyIndicatorChangeNotification`, `AppStatusExEvent`, `TestLoadedCountNotification`.
- `DTS.Common.Interface` - Likely defines `ITestSummaryListViewModel` (inferred).
- `DTS.Viewer.TestSummaryList.ViewModel` - `ITestSummaryListViewModel`, `TestSummaryViewListModel`.
- `Prism.Events.IEventAggregator` - Event aggregation pattern.
- `System.Windows.Threading.Dispatcher` - For async UI dispatching.
### Event Types Referenced:
- `BusyIndicatorChangeNotification` - Payload: `bool`
- `AppStatusExEvent` - Payload: `AppStatusExArg`
- `TestLoadedCountNotification` - Payload: `TestLoadedCountNotificationArg`
- `AppStatusArg` - Enum with `Busy` and `Available` members.
---
## 5. Gotchas
1. **Unassigned Property:** `IsSaved` is a get-only auto-property with no visible assignment. The ReSharper comment `// ReSharper disable UnassignedGetOnlyAutoProperty` indicates this is a known issue. Behavior is undefined.
2. **Naming Convention Violation:** `_eventAggregator` is a public property prefixed with an underscore, which violates typical C# naming conventions for public members.
3. **Nested Try-Catch with Silent Failure:** The inner try-catch block (lines 83-92) silently swallows all exceptions. The comment indicates this was added for a regression build to prevent crashes from a new feature (case 16158).
4. **Async Void Lambda:** The `InvokeAsync` uses an `async` lambda, but the outer method returns `void`. Exception handling is done inside the lambda, but any unhandled exceptions before the first `await` could be problematic.
5. **Collection Event Subscription:** When `Parent.TestSummaryList` is empty, the new list is assigned directly with `CollectionChanged` subscription. When non-empty, items are added individually without apparent `CollectionChanged` subscription on individual items.
6. **Historical Bug Fixes:** Multiple manuscript case references in comments (28164, 35546, 16158) indicate this class has accumulated patches for specific edge cases around test selection and identification logic.

View File

@@ -0,0 +1,37 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:54:52.641323+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "3de23a946bdde4b4"
---
# Documentation: DTS.Viewer.TestSummaryList Assembly Configuration
## 1. Purpose
This file provides assembly-level metadata and configuration for the `DTS.Viewer.TestSummaryList` module (compiled as `DTS.Viewer.Test`). It defines the assembly's identity, version, and visibility settings using standard .NET attributes. This module exists to encapsulate specific functionality within the larger DTS Viewer application, likely related to displaying lists of test summaries.
## 2. Public Interface
This file does not contain executable classes or methods. It exposes configuration via the following assembly-level attributes:
* **`AssemblyTitle`**: Set to `"DTS.Viewer.Test"`. Provides a friendly name for the assembly.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.Test"`. Specifies the product name this assembly belongs to.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`. Specifies the version of the assembly used by the common language runtime.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`. Specifies the file version number displayed on the file properties.
* **`ComVisible`**: Set to `false`. Makes types in this assembly invisible to COM components.
* **`Guid`**: Set to `"b2b2b862-1b93-476a-8246-91e1310c7ec7"`. A unique identifier for the assembly, required if the assembly is ever exposed to COM.
## 3. Invariants
* The assembly version is currently fixed at `1.0.0.0`.
* Types defined within this assembly are not visible to COM components (`ComVisible(false)`).
* The `Guid` attribute value `b2b2b862-1b93-476a-8246-91e1310c7ec7` is constant and uniquely identifies this specific assembly.
## 4. Dependencies
* **Internal Dependencies**: Relies on `System.Reflection`, `System.Runtime.CompilerServices`, and `System.Runtime.InteropServices` for attribute definitions.
* **External Consumers**: This assembly is likely referenced by the main `DTS Viewer` application or other modules requiring test summary list functionality.
## 5. Gotchas
* **Naming Discrepancy**: There is a mismatch between the project directory name (`DTS.Viewer.TestSummaryList`) and the configured assembly name (`DTS.Viewer.Test` via `AssemblyTitle` and `AssemblyProduct`). This could lead to confusion when referencing the assembly or locating the compiled `.dll`/`.exe` file.
* **Stale Metadata**: The `AssemblyCopyright` attribute lists the year 2017. If the codebase is active, this metadata is likely outdated.
* **Missing Description**: The `AssemblyDescription` attribute is an empty string, offering no insight into the module's specific functionality within the assembly properties.

View File

@@ -0,0 +1,116 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/Resources/StringResources.ja.Designer.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:54:20.692720+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ef8f2f0524698a0d"
---
# Documentation: DTS.Viewer.TestSummaryList.Resources
## 1. Purpose
This module provides localization infrastructure for the TestSummaryList component of the DTS Viewer application. It consists of a strongly-typed resource accessor class (`StringResources`) generated from a .resx file, and a WPF markup extension (`TranslateExtension`) that enables XAML bindings to localized strings. The module supports UI string lookup for test summary list operations including sorting, filtering, and displaying test metadata.
---
## 2. Public Interface
### `TranslateExtension` (WPF Markup Extension)
**Namespace:** `DTS.Viewer.TestSummaryList`
**Class Declaration:**
```csharp
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
```
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `TranslateExtension(string key)` | Initializes the extension with the resource key to look up. Stores the key in a private readonly field `_key`. |
| `ProvideValue` | `override object ProvideValue(IServiceProvider serviceProvider)` | Returns the localized string for `_key` from `StringResources.ResourceManager`. Returns `#stringnotfound#` if `_key` is null or empty. Returns `#stringnotfound# <key>` if the key is not found in resources. |
---
### `StringResources` (Auto-generated Resource Class)
**Namespace:** `DTS.Viewer.TestSummaryList.Resources`
**Class Declaration:**
```csharp
[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[DebuggerNonUserCode]
[CompilerGenerated]
internal class StringResources
```
| Property | Return Type | Description |
|----------|-------------|-------------|
| `ResourceManager` | `global::System.Resources.ResourceManager` (static) | Returns the cached ResourceManager instance for this assembly. Lazy-initialized on first access. |
| `Culture` | `global::System.Globalization.CultureInfo` (static) | Gets or sets the current culture for resource lookups. Overrides `CurrentUICulture` for this class. |
**Localized String Properties (all `internal static string`):**
| Property | Default Value (from comments) |
|----------|-------------------------------|
| `Browse` | "Browse..." |
| `ChannelCount` | "Channels: " |
| `Description` | "Description: " |
| `FileDate` | "File Date: " |
| `FileDateAscending` | "File Date" |
| `FileDateDescending` | "File Date (Descending)" |
| `IdAscending` | "Test ID" |
| `IdDescending` | "Test ID (Descending)" |
| `Refresh` | "Refresh" |
| `SetupNameAscending` | "Test Setup" |
| `SetupNameDescending` | "Test Setup (Descending)" |
| `Sort` | "Sort: " |
| `TestID` | "Test ID: " |
| `TestSetup` | "Test Setup: " |
| `TimeStamp` | "TimeStamp: " |
| `TimeStampAscending` | "TimeStamp" |
| `TimeStampDescending` | "TimeStamp (Descending)" |
| `Type` | "Type: " |
---
## 3. Invariants
- **Non-null return guarantee:** `TranslateExtension.ProvideValue` always returns a non-null string, never returns null.
- **Fallback behavior:** Missing or empty keys always produce a string containing `#stringnotfound#`.
- **Key preservation:** When a key is not found in resources, the returned string includes the original key name for debugging purposes.
- **Thread safety:** `StringResources.ResourceManager` uses a lazy-initialization pattern with a local temporary variable, ensuring only one `ResourceManager` instance exists.
- **Auto-generated constraint:** `StringResources` is tool-generated; manual edits will be overwritten on regeneration.
- **Visibility:** `StringResources` is `internal`, restricting access to within the `DTS.Viewer.TestSummaryList` assembly.
---
## 4. Dependencies
### This module depends on:
- `System` - For `ResourceManager`, `CultureInfo`, and base types
- `System.Windows.Markup` - For `MarkupExtension` and `MarkupExtensionReturnTypeAttribute` (WPF infrastructure)
- `System.CodeDom.Compiler` - For `GeneratedCodeAttribute` (auto-generated code marker)
- A `.resx` file (not provided in source) - The source file for `StringResources` string values
### What depends on this module:
- **Inferred:** XAML files within `DTS.Viewer.TestSummaryList` that use `{local:Translate KeyName}` syntax for localized UI strings
- **Inferred:** Code-behind files that reference `StringResources.<PropertyName>` directly
---
## 5. Gotchas
1. **Missing Japanese resource file:** `StringResources.ja.Designer.cs` is empty in the provided source. It is unclear whether this is intentional (placeholder for future localization) or a configuration issue.
2. **Debugging missing keys:** The `NotFound` constant (`#stringnotfound#`) will be visible in the UI if a key is misspelled or missing. This is intentional for debugging but could leak into production if keys are not validated.
3. **Culture not automatically set:** The `StringResources.Culture` property must be explicitly set; there is no automatic synchronization with `Thread.CurrentUICulture` beyond the default `ResourceManager` behavior.
4. **Trailing colons in labels:** Several resource strings (e.g., `ChannelCount`, `Description`, `FileDate`, `TestID`, `TestSetup`, `TimeStamp`, `Type`) include trailing colons and spaces in their default values. Removing these from the .resx could break UI layout assumptions.
5. **No parameter validation in constructor:** `TranslateExtension` accepts any string including whitespace-only strings; only `null` or empty strings trigger the fallback in `ProvideValue`.

View File

@@ -0,0 +1,78 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/View/TestSummaryView.xaml.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/View/TestSummaryListView.xaml.cs
generated_at: "2026-04-16T13:55:15.087802+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "a0b85470cc6f6727"
---
# Documentation: DTS.Viewer.TestSummaryList Views
## 1. Purpose
This module provides WPF view components for displaying and interacting with test summary data in the DTS Viewer application. It contains two code-behind classes (`TestSummaryView` and `TestSummaryListView`) that implement `ITestSummaryListView` and serve as the visual presentation layer for test summary lists. The module enables user interaction with test summary items, specifically allowing selection toggling via keyboard input.
---
## 2. Public Interface
### `TestSummaryView` (class)
**Namespace:** `DTS.Viewer.TestSummaryList`
**Implements:** `ITestSummaryListView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestSummaryView()` | Initializes the view by calling `InitializeComponent()`. |
---
### `TestSummaryListView` (class)
**Namespace:** `DTS.Viewer.TestSummaryList`
**Implements:** `ITestSummaryListView`
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `public TestSummaryListView()` | Initializes the view by calling `InitializeComponent()`. |
| `TestSummary_KeyUp` | `private void TestSummary_KeyUp(object sender, KeyEventArgs e)` | Event handler that toggles the `IsSelected` property on a `TestSummary` object when the Space key is released, provided the sender is a `ListView` with a `TestSummary` item selected. |
---
## 3. Invariants
- Both view classes implement `ITestSummaryListView` interface from `DTS.Common.Interface`.
- `TestSummary_KeyUp` handler only processes keyboard events when:
- The `sender` can be cast to a `ListView`
- The `ListView.SelectedItem` can be cast to a `TestSummary` type
- When the Space key is pressed on a valid `TestSummary` item, `e.Handled` is set to `true`; otherwise, it is set to `false`.
- The `IsSelected` property on `TestSummary` is toggled (negated) on Space key release.
---
## 4. Dependencies
### This module depends on:
| Dependency | Usage |
|------------|-------|
| `DTS.Common.Interface` | Provides `ITestSummaryListView` interface |
| `DTS.Common.Classes.Viewer.TestMetadata` | Provides `TestSummary` class |
| `DTS.Common.Interface.TestDefinition` | Imported but **not visibly used** in the provided source |
| `System.Windows` | WPF framework (`FrameworkElement`, `UIElement`) |
| `System.Windows.Controls` | Provides `ListView` control |
| `System.Windows.Input` | Provides `KeyEventArgs`, `Key` enum |
### What depends on this module:
- **Unclear from source alone** — consumers of `ITestSummaryListView` implementations are not visible in the provided files.
---
## 5. Gotchas
1. **Two similarly-named classes exist:** Both `TestSummaryView` and `TestSummaryListView` implement the same interface (`ITestSummaryListView`) within the same namespace. The relationship and distinction between these two views is unclear from the source alone.
2. **Namespace suppression directive:** The file `TestSummaryListView.xaml.cs` contains `// ReSharper disable CheckNamespace`, suggesting a mismatch between the file location and the declared namespace. This may indicate the file was moved or the namespace was renamed without relocating the file.
3. **Unused import:** The namespace `DTS.Common.Interface.TestDefinition` is imported in `TestSummaryListView.xaml.cs` but no types from it are referenced in the visible code. This may be dead code or used in the XAML portion not shown.
4. **XAML partial not shown:** Both classes are `partial` and depend on XAML-generated code via `InitializeComponent()`. The actual UI layout, bindings, and event wire-up (e.g., how `TestSummary_KeyUp` is connected) are defined in the corresponding `.xaml` files, which are not provided.

View File

@@ -0,0 +1,183 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/ViewModel/TestSummaryViewModel.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.TestSummaryList/ViewModel/TestSummaryViewListModel.cs
generated_at: "2026-04-16T13:54:46.702068+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b27cef2360f72751"
---
# Documentation: TestSummaryList ViewModels
## 1. Purpose
This module provides two ViewModel implementations (`TestSummaryViewModel` and `TestSummaryViewListModel`) for managing and displaying test summary data within the DTS Viewer application. Both classes implement `ITestSummaryListViewModel` and serve as intermediaries between test summary data models and their associated views, handling user interactions, event-based communication via Prism's EventAggregator, and data binding for test summary lists. The module supports filtering, sorting, selection tracking, and notification of changes to other application components.
---
## 2. Public Interface
### TestSummaryViewModel
**Constructor:**
```csharp
public TestSummaryViewModel(ITestSummaryListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the ViewModel, sets the View's DataContext, creates interaction requests, and subscribes to `RaiseNotification` and `DataFolderChangedEvent` events.
**Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `void Initialize()` | Empty override. |
| `Initialize` | `void Initialize(object parameter)` | Casts `parameter` to `IBaseWindowModel` and assigns to `Parent`. |
| `Activated` | `void Activated()` | Throws `NotImplementedException`. |
| `Cleanup` | `void Cleanup()` | Throws `NotImplementedException`. |
| `CleanupAsync` | `Task CleanupAsync()` | Throws `NotImplementedException`. |
| `InitializeAsync` | `Task InitializeAsync()` | Throws `NotImplementedException`. |
| `InitializeAsync` | `Task InitializeAsync(object parameter)` | Throws `NotImplementedException`. |
| `PublishSelectedTestSummaryList` | `void PublishSelectedTestSummaryList()` | Publishes `TestSummaryChangeNotification` and `TestSelectedChangedEvent` events with current selection. |
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `TestSummaryListView` | `ITestSummaryListView` | The associated view instance. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism interaction request for confirmations. |
| `ContextNavigationRegion` | `object` | Gets/sets content of `TestListRegion` on the view. |
| `SelectedTestSummary` | `TestSummary` | Currently selected test summary. |
| `SelectedTestSummaryList` | `List<ITestSummary>` | List of selected test summaries. |
| `TestSummaryList` | `ObservableCollection<ITestSummary>` | Collection of all test summaries. |
| `HeaderInfo` | `string` | Returns `"TestSummaryRegion"`. |
| `IsBusy` | `bool` | Busy indicator state. |
| `IsDirty` | `bool` | Dirty state flag. |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag. |
---
### TestSummaryViewListModel
**Constructor:**
```csharp
public TestSummaryViewListModel(ITestSummaryListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
```
Initializes the ViewModel, sets the View's DataContext, creates interaction requests, and stores dependencies.
**Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Initialize` | `void Initialize()` | Empty override. |
| `Initialize` | `void Initialize(object parameter)` | Sets `Parent`, initializes `FilterView`, attaches collection changed handlers, calls `Subscribe()`. |
| `Activated` | `void Activated()` | Publishes `FilterParameterChangedEvent` with empty parameter. |
| `Cleanup` | `void Cleanup()` | Clears all test summary collections, resets `SelectedTestSummary`, calls `PublishSelectedTestSummaryList()`. |
| `PublishSelectedTestSummaryList` | `void PublishSelectedTestSummaryList()` | Publishes `TestSummaryChangeNotification`, `TestSummaryCountNotification`, and `ResetZoomChangedEvent` events. |
| `OnFilterChanged` | `void OnFilterChanged(FilterParameterArgs args)` | Filters `FilteredTestSummaryList` based on `args.Param` matching `SetupName`, `Id`, or `Description`. |
| `RefreshDataFolder` | `void RefreshDataFolder()` | Publishes `DataFolderChangedEvent` via dispatcher. |
| `SelectDataFolder` | `void SelectDataFolder()` | Opens file dialog for `.dts` files, publishes `DataFileSelectedEvent` on selection. |
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `FilterView` | `IFilterView` | Filter view instance. |
| `View` | `ITestSummaryListView` | The associated view instance. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism interaction request for confirmations. |
| `ContextNavigationRegion` | `object` | Gets/sets DataContext of `TestListRegion` on the view. |
| `IsFilterEnabled` | `bool` | Indicates if filtering is available (true when `TestSummaryList` has items). |
| `SelectedTestSummary` | `TestSummary` | Currently selected test summary. |
| `SelectedTestSummaryList` | `List<ITestSummary>` | List of selected test summaries. |
| `TestSummaryList` | `ObservableCollection<ITestSummary>` | Full collection of test summaries. |
| `FilteredTestSummaryList` | `ObservableCollection<ITestSummary>` | Filtered/sorted view of test summaries. |
| `HeaderInfo` | `string` | Returns `"TestSummaryRegion"`. |
| `IsBusy` | `bool` | Busy indicator state. |
| `IsDirty` | `bool` | Dirty state flag. |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag. |
| `SelectedDataFolder` | `string` | Selected data folder path; setter publishes `DataFolderChangedEvent`. |
| `SelectedDataFile` | `string` | Selected data file path; setter publishes `DataFolderChangedEvent`. |
| `SortableAttributes` | `List<string>` | List of localized sortable attribute names. |
| `SelectedSortIndex` | `int` | Index of selected sort option; setter triggers `SortTestSummaryList()`. |
**Commands:**
| Command | Type | Description |
|---------|------|-------------|
| `RefreshDataFolderCommand` | `DelegateCommand` | Executes `RefreshDataFolder()`. |
| `SelectDataFolderCommand` | `DelegateCommand` | Executes `SelectDataFolder()`. |
**Nested Types:**
| Type | Description |
|------|-------------|
| `SortableAttribute` (enum) | Sort options: `TimeStampDescending`, `Timestamp`, `FileDateDescending`, `FileDate`, `IdDescending`, `Id`, `TestSetupDescending`, `TestSetup`. |
| `SortableAttributeHelper` | Helper class for localizing sort attribute display names via `StringResources`. |
---
## 3. Invariants
- **Parent Assignment:** `Initialize(object parameter)` in both classes expects `parameter` to be castable to `IBaseWindowModel` (TestSummaryViewModel) or `IBaseViewModel` (TestSummaryViewListModel); a null or incorrect type will cause an invalid cast exception.
- **Event Subscription Timing:** Event subscriptions occur in the constructor (TestSummaryViewModel) or in `Initialize` via `Subscribe()` (TestSummaryViewListModel); events published before initialization may not be received.
- **Collection Synchronization:** In `TestSummaryViewListModel`, `FilteredTestSummaryList` is automatically synchronized with `TestSummaryList` via `TestSummaryList_CollectionChanged` handler.
- **Filter Ownership:** `OnFilterChanged` only applies filtering when `FilterView.DataContext.Parent` equals `this`.
- **Data Folder Event Handling:** `OnDataFolderChanged` in `TestSummaryViewListModel` only processes events where `arg.ParentVM` matches `Parent`.
- **Property Setters with Side Effects:** `SelectedDataFolder` and `SelectedDataFile` setters publish events; setting to null or empty string returns early without publishing.
- **Sort Index Default:** `SelectedSortIndex` defaults to `(int)SortableAttribute.TimeStampDescending` (value 0).
---
## 4. Dependencies
### External Dependencies (from imports):
| Namespace | Purpose |
|-----------|---------|
| `DTS.Common.Base` | `BaseViewModel<T>` base class. |
| `DTS.Common.Classes.TestMetadata` / `DTS.Common.Classes.Viewer.TestMetadata` | `TestSummary`, `ITestSummary` interfaces. |
| `DTS.Common.Events` | Event types: `RaiseNotification`, `DataFolderChangedEvent`, `ShowStatus`, `TestSummaryChangeNotification`, `TestSelectedChangedEvent`, `FilterParameterChangedEvent`, `RefreshTestRequestEvent`, `BusyIndicatorChangeNotification`, `TestSummaryCountNotification`, `ResetZoomChangedEvent`, `DataFileSelectedEvent`. |
| `DTS.Common.Interface` | `IBaseWindowModel`, `IBaseViewModel`, `IEventAggregator` usage patterns. |
| `DTS.Common.Interface.TestDefinition` | `ITestSummaryListViewModel`, `ITestSummaryListView`. |
| `DTS.Common.Interactivity` | `NotificationContentEventArgs`. |
| `DTS.Viewer.TestSummaryList.Model` | `TestSummaryModel` for data loading. |
| `DTS.Viewer.TestSummaryList.Resources` | `StringResources` for localization. |
| `Microsoft.Practices.Prism.Events` / `Prism.Events` | `EventAggregator` pattern. |
| `Microsoft.Practices.Prism.Interactivity.InteractionRequest` / `Prism.Interactivity` | `InteractionRequest<T>`, `Notification`, `Confirmation`. |
| `Microsoft.Practices.Prism.Regions` / `Prism.Regions` | `IRegionManager`, region-based navigation. |
| `Microsoft.Practices.Unity` / `Unity` | `IUnityContainer` for dependency injection. |
| `Prism.Commands` | `DelegateCommand`. |
| `System.Windows.Forms` | `OpenFileDialog` for file selection. |
### Internal Dependencies:
- **TestSummaryModel:** Both ViewModels instantiate `TestSummaryModel` to call `GetTestSummary()` for loading data.
- **IFilterView / IFilterViewModel:** `TestSummaryViewListModel` resolves these via Unity container.
### Consumers (inferred):
- Views: `TestSummaryView` (referenced in `TestSummaryViewModel.ContextNavigationRegion`), `TestSummaryListView` (referenced in `TestSummaryViewListModel.ContextNavigationRegion`).
- Any module subscribing to `TestSummaryChangeNotification`, `TestSummaryCountNotification`, `TestSelectedChangedEvent`, or `ResetZoomChangedEvent`.
---
## 5. Gotchas
### Critical Issues:
1. **NotImplementedException Methods in TestSummaryViewModel:** The following methods throw `NotImplementedException`: `Activated()`, `Cleanup()`, `CleanupAsync()`, `InitializeAsync()`, and `InitializeAsync(object parameter)`. Calling these will crash the application.
2. **Misleading XML Documentation:** The constructor XML comment in `TestSummaryViewModel` states "Creates a new instance of the TechnologyDoFrontEditViewModel" — this appears to be a copy-paste error from another class.
3. **Event Signature Mismatch:** `TestSummaryViewModel.OnDataFolderChanged(string path)` expects a `string` parameter, while `TestSummaryViewListModel.OnDataFolderChanged(DataFolderSelectionArg arg)` expects `DataFolderSelectionArg`. The event `DataFolderChangedEvent` is subscribed by both with incompatible signatures — unclear which signature the event actually uses.
4. **new Keyword Shadowing:** Both classes use `new` keyword on `PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`, and `IsNavigationIncluded`. This suggests the base class `BaseViewModel<T>` already defines these members, and the shadowing may cause unexpected behavior when casting to base type.
5. **Direct View Casting:** `ContextNavigationRegion` property directly casts the view interface to concrete types (`TestSummaryView` or `TestSummaryListView`), breaking the interface abstraction pattern.
6. **Dispatcher Usage in RefreshDataFolder:** `RefreshDataFolder()` uses `Dispatcher.CurrentDispatcher.Invoke()` with `DispatcherPriority.Background`, which may cause timing issues if called from a non-UI thread.
7. **Sort Implementation Rebuilds Collection:** `SortTestSummaryList()` clears and rebuilds `FilteredTestSummaryList` on every sort change, which may cause UI flicker and performance issues with large datasets.
8. **Missing Unsubscribe:** Neither class unsubscribes from events in cleanup, potentially causing memory leaks if instances are not properly garbage collected.

View File

@@ -0,0 +1,83 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/ViewerSettingsModule.cs
generated_at: "2026-04-16T13:43:31.988830+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "9f0f5c6b474b7ca8"
---
# Documentation: DTS.Viewer.ViewerSettings Module
## 1. Purpose
This module serves as the entry point for the "Viewer Settings" feature within the DTS application. It is responsible for self-registering its View and ViewModel components with the Unity dependency injection container and providing assembly metadata (name, image, grouping, and region) to the broader application infrastructure. It follows the Prism modular architecture to encapsulate viewer configuration logic.
## 2. Public Interface
### `ViewerSettingsModule`
The main module class implementing `Prism.Modularity.IModule`.
* **`ViewerSettingsModule(IUnityContainer unityContainer)`**
* Constructor that accepts an `IUnityContainer` instance via dependency injection and stores it in a private readonly field `_unityContainer`.
* **`void RegisterTypes(IContainerRegistry containerRegistry)`**
* Implements `IModule.RegisterTypes`. Calls the private `Initialize()` method to perform type registrations.
* **`void OnInitialized(IContainerProvider containerProvider)`**
* Implements `IModule.OnInitialized`. Currently contains no implementation logic.
### `ViewerSettingsModuleNameAttribute`
An assembly-level attribute extending `TextAttribute` used to define the module's name.
* **`ViewerSettingsModuleNameAttribute()`**
* Default constructor.
* **`ViewerSettingsModuleNameAttribute(string s)`**
* Overloaded constructor accepting a string argument (which is unused in the body).
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.ViewerSettings`.
* **`Type GetAttributeType()`**
* Returns `typeof(TextAttribute)`.
* **`string GetAssemblyName()`**
* Returns the `AssemblyName` property value.
### `ViewerSettingsModuleImageAttribute`
An assembly-level attribute extending `ImageAttribute` used to provide visual metadata for the module.
* **`ViewerSettingsModuleImageAttribute()`**
* Default constructor.
* **`ViewerSettingsModuleImageAttribute(string s)`**
* Overloaded constructor accepting a string argument (unused in the body).
* **`BitmapImage AssemblyImage { get; }`**
* Retrieves an image using `AssemblyInfo.GetImage(AssemblyNames.ViewerSettings.ToString())`.
* **`string AssemblyName { get; }`**
* Returns the string representation of `AssemblyNames.ViewerSettings`.
* **`string AssemblyGroup { get; }`**
* Returns `eAssemblyGroups.Viewer.ToString()`.
* **`eAssemblyRegion AssemblyRegion { get; }`**
* Returns `eAssemblyRegion.ViewerSettingsRegion`.
* **Methods**: `GetAttributeType()`, `GetAssemblyImage()`, `GetAssemblyName()`, `GetAssemblyGroup()`, `GetAssemblyRegion()` return the values of their respective properties.
## 3. Invariants
* **Registration Mapping:** The module registers the interface `IViewerSettingsView` to the concrete type `ViewerSettingsView` and `IViewerSettingsViewModel` to `ViewerSettingsViewModel`.
* **Attribute Usage:** Both `ViewerSettingsModuleNameAttribute` and `ViewerSettingsModuleImageAttribute` are decorated with `AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)`, ensuring they appear only once per assembly.
* **Naming Consistency:** The `AssemblyName` property in both attribute classes is hardcoded to the `AssemblyNames.ViewerSettings` enum value.
* **Region Assignment:** The module is explicitly assigned to the `eAssemblyRegion.ViewerSettingsRegion`.
## 4. Dependencies
### Internal Dependencies (Inferred from usage)
* **`DTS.Common`**: Used for `AssemblyNames`, `eAssemblyGroups`, `eAssemblyRegion`, and `AssemblyInfo`.
* **`DTS.Common.Interface`**: Defines `TextAttribute`, `ImageAttribute`, `IViewerSettingsView`, and `IViewerSettingsViewModel`.
* **`ViewerSettingsView` / `ViewerSettingsViewModel`**: Concrete types referenced in `Initialize()` (source not provided, assumed to exist in this or a related assembly).
### External Libraries
* **`Prism.Ioc`**: Provides `IContainerProvider`, `IContainerRegistry`.
* **`Prism.Modularity`**: Provides `IModule`.
* **`Unity`**: Provides `IUnityContainer` (Microsoft.Practices.Unity).
* **`System.Windows.Media.Imaging`**: Provides `BitmapImage`.
## 5. Gotchas
* **Mixed Container Abstractions:** The `RegisterTypes` method receives an `IContainerRegistry` (Prism abstraction) but ignores it. Instead, it calls `Initialize()`, which uses the injected `IUnityContainer` (concrete Unity implementation) directly. This bypasses Prism's container abstraction, which could cause issues if the container implementation is swapped or if the registry context is required for specific Prism features.
* **Commented-Out Registration:** The line `_unityContainer.RegisterType<IViewerSettingsModel, ViewerSettingsModel>();` is commented out. It is unclear if the Model is intentionally excluded, obsolete, or if this is incomplete work.
* **Unused Constructor Parameters:** Both attribute classes (`ViewerSettingsModuleNameAttribute` and `ViewerSettingsModuleImageAttribute`) define constructors that accept a `string s` parameter but never use it. This suggests legacy refactoring or a design pattern where the parameter is ignored.
* **Property Side-Effects:** In `ViewerSettingsModuleImageAttribute`, the `AssemblyImage` property getter modifies the private field `_img` (lazy initialization pattern inside a getter). This is a side-effect that can be confusing during debugging.

View File

@@ -0,0 +1,47 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/Properties/AssemblyInfo.cs
generated_at: "2026-04-16T13:50:25.888352+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "aa69b1de52a95e40"
---
# Properties
## 1. Purpose
This file provides assembly-level metadata attributes for the `DTS.Viewer.ViewerSettings` module. It defines identity information (title, product), versioning details, and COM visibility settings for the compiled .NET assembly. It serves as the standard assembly manifest configuration, typically auto-generated by Visual Studio for .NET Framework projects, to identify the module within the larger "DTS Viewer" application ecosystem.
## 2. Public Interface
This file does not contain public classes or methods. Instead, it configures the following assembly-level attributes:
* **`AssemblyTitle`**: Set to `"DTS.Viewer.ViewerSettings"`. Provides a friendly name for the assembly.
* **`AssemblyDescription`**: Set to an empty string.
* **`AssemblyProduct`**: Set to `"DTS.Viewer.ViewerSettings"`. Provides product information.
* **`AssemblyCopyright`**: Set to `"Copyright © 2019"`.
* **`ComVisible`**: Set to `false`. Ensures types within this assembly are not visible to COM components by default.
* **`Guid`**: Set to `"4733690a-cb08-4c2e-853a-9339be13ac28"`. A unique identifier for the assembly, used if the project is exposed to COM.
* **`AssemblyVersion`**: Set to `"1.0.0.0"`. Defines the version of the assembly used by the common language runtime.
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`. Defines the file version number displayed on the file properties.
## 3. Invariants
* **COM Visibility:** Types within this assembly are explicitly hidden from COM components (`ComVisible(false)`).
* **Versioning:** Both the assembly version and file version are fixed at `1.0.0.0`.
* **Identity:** The `Guid` is constant and uniquely identifies this specific assembly module.
## 4. Dependencies
* **Imports:**
* `System.Reflection`
* `System.Runtime.CompilerServices`
* `System.Runtime.InteropServices`
* **Dependents:** The compiled assembly (`DTS.Viewer.ViewerSettings.dll`) is the direct consumer of this metadata. Other modules within the "DTS Viewer" solution may reference this assembly, but they do not depend on this specific source file directly.
## 5. Gotchas
* **Hardcoded Versions:** The `AssemblyVersion` and `AssemblyFileVersion` are hardcoded to `1.0.0.0`. Unlike modern SDK-style projects which may derive versioning from build pipelines, this file requires manual updates or a build task to modify version numbers for new releases.
* **Empty Description:** The `AssemblyDescription` attribute is explicitly empty, which may result in missing metadata in assembly browsers or deployment tools.
* **Stale Copyright:** The copyright string is hardcoded to 2019. If the codebase is active, this date is likely outdated.

View File

@@ -0,0 +1,73 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/Resources/TranslateExtension.cs
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/Resources/StringResources.Designer.cs
generated_at: "2026-04-16T13:50:32.426485+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b58f3ee343f377b9"
---
# Documentation: DTS.Viewer.ViewerSettings.Resources
## 1. Purpose
This module provides localization infrastructure for the `DTS.Viewer.ViewerSettings` namespace. It consists of a strongly-typed resource accessor class (`StringResources`) generated from a `.resx` file, and a XAML markup extension (`TranslateExtension`) that allows UI elements to bind directly to localized strings using the resource keys. This separates user-facing text from code logic and supports multi-language deployments.
## 2. Public Interface
### `TranslateExtension`
**Location:** `DTS.Viewer.ViewerSettings`
**Inheritance:** `System.Windows.Markup.MarkupExtension`
A XAML markup extension used to resolve localized strings in the UI layer.
* **`TranslateExtension(string key)`**
* Constructor that accepts the resource key to be translated.
* **`object ProvideValue(IServiceProvider serviceProvider)`**
* Returns the localized string corresponding to the `_key`.
* Returns `#stringnotfound#` if the key is null or empty.
* Returns `#stringnotfound# {key}` if the lookup fails for a specific key.
### `StringResources`
**Location:** `DTS.Viewer.ViewerSettings.Resources`
**Attributes:** `internal`, Auto-generated
A strongly-typed resource class providing access to localized strings.
* **`static global::System.Resources.ResourceManager ResourceManager`**
* Returns the cached `ResourceManager` instance for this assembly.
* **`static global::System.Globalization.CultureInfo Culture`**
* Gets or sets the `CultureInfo` used for resource lookups. Overrides the current thread's `CurrentUICulture`.
* **`static string CalibrationBehavior_LinearIfAvailable`**
* Resource string: "Use the linear sensitivity, if available."
* **`static string CalibrationBehavior_NonLinearIfAvailable`**
* Resource string: "Use the non-linear sensitivity, if available."
* **`static string CalibrationBehavior_UseBothIfAvailable`**
* Resource string: "Use both sensitivities, if available, as separate channels."
* **`static string CalibrationBehaviorText`**
* Resource string: "Calibration Behavior".
## 3. Invariants
* **Non-Null Return:** `TranslateExtension.ProvideValue` always returns a string; it never returns null. It guarantees a fallback string if the resource is missing.
* **Fallback Format:** If a resource key is valid but not found, the return value follows the format `#stringnotfound# {key}`.
* **Empty Key Handling:** If the key passed to `TranslateExtension` is null or empty, the return value is exactly `#stringnotfound#` (without a trailing space or key name).
* **Visibility:** `StringResources` is marked `internal`, restricting access to within the assembly.
* **Code Generation:** `StringResources` is auto-generated; manual edits to the file will be overwritten by the tooling (ResGen/Visual Studio).
## 4. Dependencies
* **Internal Dependencies:**
* `TranslateExtension` depends on `StringResources` to perform the actual resource lookup via `StringResources.ResourceManager`.
* **External Framework Dependencies:**
* `System.Windows.Markup`: Required for `MarkupExtension` and `IServiceProvider` (WPF specific).
* `System.Resources`: Required for `ResourceManager`.
* `System.Globalization`: Required for `CultureInfo`.
* **File Dependencies:**
* `StringResources.Designer.cs` depends on an underlying `.resx` file (likely `StringResources.resx`) which contains the actual key-value pairs for the localized strings.
## 5. Gotchas
* **Culture Inconsistency:** `TranslateExtension` calls `StringResources.ResourceManager.GetString(_key)` without passing a culture argument. This relies on `Thread.CurrentUICulture`. However, `StringResources` exposes a static `Culture` property. If a developer sets `StringResources.Culture` explicitly, the strongly-typed properties (e.g., `CalibrationBehaviorText`) will respect it, but `TranslateExtension` will **ignore** it and continue using the thread's current UI culture.
* **Silent Failures:** The `TranslateExtension` does not throw exceptions for missing keys. Instead, it returns the error string `#stringnotfound#`. This is designed for debugging visibility but requires visual inspection of the UI to detect missing translations.
* **Designer File Edits:** Because `StringResources.Designer.cs` is auto-generated, developers must not add custom logic or properties directly to this class. Changes must be made in the corresponding `.resx` file.

View File

@@ -0,0 +1,57 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/View/ViewerSettingsView.xaml.cs
generated_at: "2026-04-16T13:50:42.982175+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "499d220096c49a25"
---
# Documentation: ViewerSettingsView.xaml.cs
## 1. Purpose
This module provides the code-behind implementation for `ViewerSettingsView`, a WPF User Control that serves as the UI component for configuring viewer settings within the DTS Viewer application. It implements the `IViewerSettingsView` interface, indicating it follows a view abstraction pattern (likely MVP or MVVM), allowing the view to be consumed by a presenter or view model without direct coupling to the concrete implementation.
## 2. Public Interface
### `ViewerSettingsView` (class)
**Kind:** `public partial class`
**Implements:** `IViewerSettingsView`
**Location:** Namespace `DTS.Viewer.ViewerSettings`
#### Constructor
```csharp
public ViewerSettingsView()
```
Initializes a new instance of the `ViewerSettingsView` class. Calls `InitializeComponent()`, which loads and instantiates the associated XAML-defined UI element tree.
---
**Note:** No other public members are defined in this code-behind file. Any additional public properties, commands, or event handlers would be defined in the accompanying XAML file or generated as part of the partial class definition.
## 3. Invariants
- The class is `partial`, meaning it must be paired with a corresponding XAML file (`ViewerSettingsView.xaml`) that defines the UI layout.
- `InitializeComponent()` must be called exactly once during construction; this is generated code from the XAML and is essential for the control to function.
- The class implements `IViewerSettingsView`, so it must satisfy all members defined by that interface (interface members are not visible in this source alone).
## 4. Dependencies
### This module depends on:
- **`DTS.Common.Interface`** — Provides the `IViewerSettingsView` interface contract.
- **WPF Framework** (`System.Windows.*`) — Core WPF types for user controls, controls, data binding, input, and media rendering.
### What depends on this module:
- **Unclear from source alone.** Consumers would include whatever module instantiates or resolves `ViewerSettingsView` (likely a presenter, view model, or DI container configuration).
## 5. Gotchas
- **Unused using directives:** The file imports `System.Collections.Generic`, `System.Linq`, `System.Text`, `System.Threading.Tasks`, and several WPF namespaces that are not referenced anywhere in the code. These are likely remnants of the Visual Studio item template and could be removed.
- **Interface contract unknown:** The requirements of `IViewerSettingsView` are not visible in this source. Developers must consult `DTS.Common.Interface` to understand what members this view must implement.
- **No observable behavior:** The code-behind contains only the constructor. All meaningful interaction logic is presumably handled via XAML bindings, code-behind event handlers not shown here, or is entirely delegated to a view model.

View File

@@ -0,0 +1,120 @@
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.ViewerSettings/ViewModel/ViewerSettingsViewModel.cs
generated_at: "2026-04-16T13:49:48.286150+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "f93455d3d5a535ba"
---
# Documentation: ViewerSettingsViewModel
## 1. Purpose
`ViewerSettingsViewModel` is a Prism-based view model for the Viewer Settings module within the DTS Viewer application. It manages user-configurable settings related to calibration behaviors, handles visibility states for settings UI elements, and coordinates with parent view models via event aggregation. The class serves as the binding context for `IViewerSettingsView` and participates in the application's region-based navigation system.
---
## 2. Public Interface
### Constructor
```csharp
public ViewerSettingsViewModel(
IViewerSettingsView view,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the view model, sets the view's DataContext to itself, and creates `NotificationRequest` and `ConfirmationRequest` interaction requests.
### Methods
```csharp
public override void Initialize()
```
Empty override. No initialization logic performed.
```csharp
public override void Initialize(object parameter)
```
Sets `Parent` property from the provided parameter (cast to `IBaseViewModel`) and calls `Subscribe()` to register event handlers.
```csharp
public void PublishChanges()
```
Empty implementation. No behavior defined in source.
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IViewerSettingsView` | Gets/sets the associated view interface. |
| `Parent` | `IBaseViewModel` | Gets/sets the parent view model reference. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for confirmations (hides base member with `new`). |
| `HeaderInfo` | `string` | Returns constant string `"SettingsRegion"`. |
| `IsBusy` | `bool` | Gets/sets busy state (hides base member with `new`). |
| `IsDirty` | `bool` | Gets/sets dirty state (hides base member with `new`). |
| `IsNavigationIncluded` | `bool` | Gets/sets navigation inclusion flag (hides base member with `new`). |
| `CalibrationBehaviorSettingVisibility` | `Visibility` | Controls visibility of calibration behavior setting UI. Publishes `ViewerSettingsVisibilityChangedEvent` when changed. |
| `OverallSettingsVisibility` | `Visibility` | Computed property; returns `Visibility.Visible` if `CalibrationBehaviorSettingVisibility` is visible, otherwise `Visibility.Collapsed`. |
| `AvailableCalibrationBehaviors` | `DisplayedCalibrationBehavior[]` | Lazily-initialized, thread-safe array of three calibration behavior options: `_linearIfAvail`, `_nonLinearIfAvail`, `_useBothIfAvail`. |
| `CalibrationBehaviorSetting` | `DisplayedCalibrationBehavior` | Gets/sets the selected calibration behavior. Defaults to `CalibrationBehaviors.NonLinearIfAvailable`. Publishes `CalibrationBehaviorSettingChangedEvent` when changed. |
### Events
```csharp
public new event PropertyChangedEventHandler PropertyChanged
```
Hides base class event. Raised via `OnPropertyChanged(string)`.
---
## 3. Invariants
- **Default Calibration Behavior**: `_calibrationBehaviorSetting` is always initialized to `CalibrationBehaviors.NonLinearIfAvailable`.
- **OverallSettingsVisibility Dependency**: `OverallSettingsVisibility` is always `Visibility.Collapsed` when `CalibrationBehaviorSettingVisibility` is `Visibility.Collapsed`. It cannot be visible independently.
- **Thread Safety**: `AvailableCalibrationBehaviors` getter uses a lock (`MyLock`) to ensure thread-safe lazy initialization.
- **CalibrationBehaviorSetting Getter**: Always returns a matching `DisplayedCalibrationBehavior` from `AvailableCalibrationBehaviors` array, or `null` if no match found.
- **Event Subscription Timing**: Subscriptions occur only after `Initialize(object parameter)` is called, not in the constructor.
---
## 4. Dependencies
### External Dependencies (from imports)
- **Prism.Events** - `IEventAggregator` for pub/sub messaging
- **Prism.Regions** - `IRegionManager` for region-based navigation
- **Unity** - `IUnityContainer` for dependency injection
- **DTS.Common.Base** - `BaseViewModel<T>`, `IBaseViewModel`
- **DTS.Common.Classes.Sensors** - `DisplayedCalibrationBehavior`
- **DTS.Common.Enums.Sensors** - `CalibrationBehaviors` enum
- **DTS.Common.Events** - `CalibrationBehaviorSettingChangedEvent`, `CalibrationBehaviorSettableInViewerChangedEvent`, `ViewerSettingsVisibilityChangedEvent`
- **DTS.Common.Interactivity** - `InteractionRequest<T>`, `Notification`, `Confirmation`
- **DTS.Common.Interface** - `IViewerSettingsViewModel`
- **System.Windows** - `Visibility` enum
### Consumed Events
- `CalibrationBehaviorSettingChangedEvent` - payload: `CalibrationBehaviors`
- `CalibrationBehaviorSettableInViewerChangedEvent` - payload: `bool`
### Published Events
- `CalibrationBehaviorSettingChangedEvent` - published when `CalibrationBehaviorSetting` setter is invoked with a different value
- `ViewerSettingsVisibilityChangedEvent` - published when `CalibrationBehaviorSettingVisibility` is set
---
## 5. Gotchas
1. **Misleading XML Documentation**: The constructor's XML comment references `TestSummaryViewListModel`, which appears to be a copy-paste error from another class.
2. **Member Hiding with `new` Keyword**: Multiple members (`PropertyChanged`, `OnPropertyChanged`, `IsBusy`, `IsDirty`, `IsNavigationIncluded`, `ConfirmationRequest`) hide base class members using `new`. This breaks polymorphism—consumers casting to the base type will invoke base implementations, not these overrides.
3. **Empty `PublishChanges()` Method**: The method has no implementation. Its intended purpose is unclear from source alone.
4. **Cascading Visibility Notifications**: `OnPropertyChanged` has special logic—any property name ending with `"Visibility"` (except `"OverallSettingsVisibility"`) triggers an additional `OnPropertyChanged("OverallSettingsVisibility")` call. This side effect is not obvious from property setters alone.
5. **Potential Null Return**: `CalibrationBehaviorSetting` getter returns `null` if `_calibrationBehaviorSetting` does not match any item in `AvailableCalibrationBehaviors`. Callers should handle this possibility.
6. **No Unsubscribe Logic**: The class subscribes to events in `Subscribe()` but does not appear to unsubscribe. Potential memory leak if view model lifecycle is shorter than the event aggregator's.