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,40 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/GroupChannelListModule.cs
generated_at: "2026-04-17T16:46:52.499953+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b6c76c982c83d2d8"
---
# Documentation: GroupChannelListModule
## 1. Purpose
This module provides the "Group Channel List" functionality within a modular WPF application built on the Prism framework. It serves as a self-contained unit that registers views and view-models for group channel listing and settings management with the Unity dependency injection container. The module is categorized under the "Prepare" assembly group and exposes assembly-level metadata (name and image) for use by the main application shell, likely for module discovery and UI presentation purposes.
## 2. Public Interface
### `GroupChannelListModule` (class)
**Implements:** `Prism.Modularity.IModule`
The main module class responsible for type registration with the DI container.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GroupChannelListModule(IUnityContainer unityContainer)` | Accepts a Unity container instance via constructor injection. |
| `Initialize` | `void Initialize()` | Registers three type mappings with Unity: `IGroupChannelListViewModel``GroupChannelListViewModel`, `IGroupChannelListView``GroupChannelListView`, `IGroupChannelSettingsListView``GroupChannelSettingsListView`. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Empty implementation. No post-initialization logic executed. |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Delegates to `Initialize()`. This is the Prism lifecycle method for type registration. |
---
### `GroupChannelListModuleNameAttribute` (class)
**Inherits from:** `TextAttribute`
Assembly-level attribute exposing the module's name as text metadata.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GroupChannelListModuleNameAttribute()` | Default constructor; sets `AssemblyName` to `AssemblyNames.GroupChannelList.ToString()`. |
| Constructor | `GroupChannelListModuleNameAttribute(string s)` | Overload accepting a string parameter (parameter is unused).

View File

@@ -0,0 +1,31 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Converters/BooleanToWidthConverter.cs
- DataPRO/Modules/Groups/GroupChannelList/Converters/SensorIdBackgroundConverter.cs
generated_at: "2026-04-17T16:13:20.076259+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "e25d08690ef1d9de"
---
# Converters
### Purpose
This module provides WPF value converters for the `GroupChannelList` UI component. It exists to transform data values into visual representations in XAML bindings, specifically converting boolean values to width measurements and background brush colors for sensor ID display elements.
### Public Interface
- **`BooleanToWidthConverter` class** (public) - Implements `IValueConverter`. Converts boolean values to width values for UI element sizing.
- `object Convert(object value, Type targetType, object parameter, CultureInfo culture)` - Returns `width` (parsed from parameter) if `value` is `true`, returns `0` if `value` is `false`, returns `0` if `value` is `null`. If parameter parsing fails, returns `double.NaN`.
- `object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)` - Throws `NotImplementedException`.
- **`SensorIdBackgroundConverter` class** (public) - Implements `IValueConverter`. Converts boolean values to background brush colors.
- `object Convert(object value, Type targetType, object parameter, CultureInfo culture)` - Returns a light green brush (`#FFE3FBE1`) if `value` is `true`, returns `Brushes.Transparent` if `value` is `false` or `null`. Catches and traces exceptions.
- `object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)` - Throws `NotImplementedException`.
### Invariants
- `ConvertBack` is not implemented on either converter; these are one-way converters only.
- `SensorIdBackgroundConverter.SensorIdBrush` is a static field that is frozen before return to make it thread-safe and non-modifiable.
### Dependencies
- **Depends on**: `System.Windows.Data.IValueConverter`, `System.Windows.Media.SolidColorBrush`, `System.Windows.Media.Color`, `System.Windows.Media.Brushes`, `System.Globalization.CultureInfo`, `System.Diagnostics.Trace`.
- **Depended on by**: XAML views in the `GroupChannelList

View File

@@ -0,0 +1,38 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Properties/Settings.Designer.cs
- DataPRO/Modules/Groups/GroupChannelList/Properties/AssemblyInfo.cs
generated_at: "2026-04-17T16:13:20.076523+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "db9235aae8cb1ff1"
---
# Properties
### Purpose
This module provides assembly metadata and application-scoped configuration settings for the `RegAddProductCode` custom installer action. It exists to configure Windows Installer policy-related registry operations, specifically for managing secure repair whitelisting. The settings defined here are used during installation to register product codes that allow the application to be repaired without elevated privileges.
### Public Interface
- **`Settings` class** (internal sealed, partial) - Auto-generated settings class inheriting from `System.Configuration.ApplicationSettingsBase`.
- `static Settings Default { get; }` - Returns the synchronized singleton instance of settings.
- `string InstallerKey { get; }` - Returns `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer"`. Application-scoped setting.
- `string MissingKey { get; }` - Returns `"No key at {0}"`. Format string template for missing key messages. Application-scoped setting.
- `string ProductCode { get; }` - Returns `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"`. The GUID product code for this product. Application-scoped setting.
- `string SecureRepairPolicy { get; }` - Returns `"SecureRepairPolicy"`. Application-scoped setting.
- `string SecureRepairWhitelistKey { get; }` - Returns `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer\\SecureRepairWhitelist"`. Application-scoped setting.
### Invariants
- All settings are application-scoped and read-only at runtime.
- The `ProductCode` GUID must be a valid Windows Installer product code format.
- Registry key paths use double backslash escaping for .NET string literals.
### Dependencies
- **Depends on**: `System.Configuration.ApplicationSettingsBase`, `System.Runtime.CompilerServices`, `System.Runtime.InteropServices`.
- **Depended on by**: The parent `RegAddProductCode` installer custom action module (inferred from namespace).
### Gotchas
- The `MissingKey` setting contains a format placeholder `{0}` suggesting it's intended for `string.Format()` usage, but the consuming code is not visible in this module.
- The `ProductCode` GUID `{C4889149-0CAF-44C1-B226-8F6E73684DF4}` is hardcoded; if the actual product code changes, this setting must be updated manually.
---

View File

@@ -0,0 +1,216 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupChannelList/Resources/StringResources.Designer.cs
generated_at: "2026-04-17T15:58:50.253166+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "fc71a9ad19b8ef2b"
---
# Documentation: GroupChannelList Resources Module
## 1. Purpose
This module provides localization infrastructure for the GroupChannelList feature within the DataPRO Groups module. It consists of a WPF XAML markup extension (`TranslateExtension`) that enables declarative string localization in XAML bindings, backed by an auto-generated strongly-typed resource class (`StringResources`) containing localized strings for channel configuration UI elements, parameter labels, validation messages, and user-facing text. The module supports the configuration and display of various channel types including Analog, CAN, Digital I/O, Squib, Stream, and UART channels.
---
## 2. Public Interface
### TranslateExtension (Markup Extension)
**Class Definition:**
```csharp
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
```
**Constructor:**
```csharp
public TranslateExtension(string key)
```
- Creates an instance with the specified resource key to look up.
**Public Method:**
```csharp
public override object ProvideValue(IServiceProvider serviceProvider)
```
- Returns the localized string for the key stored in `_key` by querying `StringResources.ResourceManager.GetString(_key)`.
- Returns `NotFound` ("#stringnotfound#") if `_key` is null or empty.
- Returns `NotFound + " " + _key` (e.g., "#stringnotfound# SomeKey") if the resource lookup returns null.
**Private Constants:**
- `private const string NotFound = "#stringnotfound#"` — Fallback value for missing keys.
---
### StringResources (Auto-Generated Resource Class)
**Class Definition:**
```csharp
internal class StringResources
```
- Internal class; not accessible outside the `GroupChannelList.Resources` namespace.
**Static Properties:**
| Property | Description (from source comments) |
|----------|-------------------------------------|
| `ResourceManager` | Returns cached `ResourceManager` instance for this assembly. |
| `Culture` | Gets/sets `CultureInfo` for resource lookups. |
**Resource String Properties (selected):**
| Property | Default Text |
|----------|--------------|
| `AnalogParameter_ACCouplingEnable` | "AC coupling enabled" |
| `AnalogParameters_Capacity` | "Sensor max range" |
| `AnalogParameters_CFC` | "Channel filter class" |
| `AnalogParameters_InitialOffset` | "Initial offset" |
| `AnalogParameters_MaximumUsage` | "Maximum Usage" |
| `AnalogParameters_Polarity` | "Polarity" |
| `AnalogParameters_Range` | "Channel full-scale" |
| `AnalogParameters_Sensitivity` | "Sensitivity" |
| `AnalogParameters_Units` | "Units" |
| `AnalogParameters_UsageCount` | "Usage Count" |
| `AnalogParameters_UserValue1/2/3` | "User Value 1/2/3" |
| `AnalogParameters_ZeroMethod` | "Zero Method" |
| `AnalogParameters_ZeroMethodEnd` | "End (sec)" |
| `AnalogParameters_ZeroMethodStart` | "Start (sec)" |
| `CanParameters_ArbBaseBitrate` | "Arb/Base Bitrate" |
| `CanParameters_ArbBaseSJW` | "Arb/Base SJW" |
| `CanParameters_DataBitrate` | "Data Bitrate" |
| `CanParameters_DataSJW` | "Data SJW" |
| `CanParameters_FileType` | "FileType" |
| `CanParameters_IsFD` | "CAN is FD" |
| `DigitalInParameters_ActiveValue` | "Active value" |
| `DigitalInParameters_DefaultValue` | "Default value" |
| `DigitalInParameters_InputMode` | "Input mode" |
| `DigitalOutParameters_Delay` | "Delay (ms)" |
| `DigitalOutParameters_Duration` | "Duration (ms)" |
| `DigitalOutParameters_LimitDuration` | "Limit duration" |
| `DigitalOutParameters_OutputMode` | "Output mode" |
| `SquibParameters_Current` | "Current (A)" |
| `SquibParameters_Delay` | "Delay (ms)" |
| `SquibParameters_Duration` | "Duration (ms)" |
| `SquibParameters_FireMode` | "Fire mode" |
| `SquibParameters_LimitDuration` | "Limit duration" |
| `StreamInParameters_UDPAddress` | "UDP Address" |
| `StreamOutParameters_DataChannelId` | "Data channel id" |
| `StreamOutParameters_IENA_Key` | "IENA key" |
| `StreamOutParameters_IENA_SourcePort` | "Source port" |
| `StreamOutParameters_IRIGTimeDataPacketIntervalMs` | "IRIG time data packet interval (ms)" |
| `StreamOutParameters_StreamProfile` | "Stream profile" |
| `StreamOutParameters_TimeChannelId` | "Time channel id" |
| `StreamOutParameters_TMATSIntervalMs` | "TMATS interval (ms)" |
| `StreamOutParameters_TMNS_MessageId` | "Message Id" |
| `StreamOutParameters_TMNS_MinorPerMajor` | "Minor per major" |
| `StreamOutParameters_TMNS_SubFrameId` | "Subframe Id" |
| `StreamOutParameters_TMNS_TMATSPort` | "TMATS port" |
| `StreamOutParameters_TmNSConfig` | "TmNS config" |
| `StreamOutParameters_UDPAddress` | "UDP Address" |
| `UartParameters_BaudRate` | "Baud rate" |
| `UartParameters_DataBits` | "Data bits" |
| `UartParameters_DataFormat` | "Data format" |
| `UartParameters_FlowControl` | "Flow control" |
| `UartParameters_Parity` | "Parity" |
| `UartParameters_StopBits` | "Stop bits" |
| `ChannelName` | "Channel name" |
| `ChannelType` | "Type" |
| `Channels` | " channel(s) in " |
| `Clear` | "Clear" |
| `Delete` | "Delete" |
| `DisplayName` | "Display name" |
| `DisplayOrder` | "Display order" |
| `DragAndDropFilterWarning` | "Drag and drop operation completed. Note that the table is currently being filtered..." |
| `DuplicateSensor` | "Sensor appears more than once" |
| `EnterValue` | "Enter value" |
| `GlobalRangeCAC` | "Global range (CAC)" |
| `Group` | "Group" |
| `GroupLower` | "group" |
| `Hardware` | "Hardware" |
| `IEPESupport` | "IEPE support" |
| `IntervalOn` | "On" |
| `InvalidAnalogAssignment` | "Sensor {0} can not be assigned to channel {1}" |
| `InvalidDigitalInputAssignment` | "DigitalInput {0} can not be assigned to channel {1}" |
| `InvalidDigitalOutputAssignment` | "DigitalOutput {0} can not be assigned to channel {1}" |
| `InvalidExcitationAssignment` | "Sensor {0} does not support any of the excitation options provided by channel {1}" |
| `InvalidLine` | "Invalid pasted group channel, line: {0}" |
| `InvalidSensor` | "Invalid sensor, line: {0}" |
| `InvalidSquibAssignment` | "Squib {0} can not be assigned to channel {1}" |
| `ISOAndUserCode` | "ISO 13499 and user codes" |
| `ISOChannelName` | "ISO channel name" |
| `ISOCode` | "ISO (13499) code" |
| `ISOOnly` | "ISO 13499 only" |
| `ModifyGlobalRangeCAC` | "Modify global range CAC" |
| `Not_Applicable` | "N/A" |
| `Of` | " of " |
| `Order` | "Order" |
| `Parameters_Analog` | "Analog" |
| `Parameters_CAN` | "CAN" |
| `Parameters_DigitalIn` | "Digital in" |
| `Parameters_DigitalOut` | "Digital out" |
| `Parameters_Squib` | "Squib" |
| `Parameters_StreamIn` | "Stream in" |
| `Parameters_StreamOut` | "Stream out" |
| `Parameters_Uart` | "UART" |
| `PhysicalChannelsAssigned` | " physical channel(s) assigned" |
| `RemoveSensor` | "Remove Sensor" |
| `Sensor` | "Sensor (SN)" |
| `DallasId` | "Dallas ID" |
| `AssignedBySensorId` | "(Assigned by ID)" |
| `btnApplyGlobalRangeCAC` | "Apply" |
| `ChannelDelete_Tooltip` | "To delete a channel, please contact an Administrator" |
| `Table_NA` | "---" |
| `Test` | "test" |
| `TestChannelsGroupName` | "Test channels" |
| `UserChannelName` | "User channel name" |
| `UserCode` | "User code" |
| `UserCodeOnly` | "User codes only" |
---
## 3. Invariants
1. **TranslateExtension key requirement**: The `_key` field is set via constructor and is `readonly`. It cannot be changed after instantiation.
2. **Missing resource handling**: `ProvideValue` will never return null. It returns either:
- The localized string from resources
- `#stringnotfound#` (if key is null/empty)
- `#stringnotfound# {key}` (if key exists but no matching resource)
3. **StringResources visibility**: The `StringResources` class is `internal` and cannot be accessed outside the `GroupChannelList.Resources` namespace.
4. **ResourceManager singleton pattern**: The `ResourceManager` property uses lazy initialization with a null-check pattern; once initialized, the same instance is returned on subsequent calls.
5. **Auto-generated code constraint**: `StringResources.Designer.cs` is auto-generated by `System.Resources.Tools.StronglyTypedResourceBuilder` version 17.0.0.0. Manual changes will be overwritten on regeneration.
---
## 4. Dependencies
### This module depends on:
- `System` (core .NET framework)
- `System.Windows.Markup` (for `MarkupExtension` and `MarkupExtensionReturnTypeAttribute`) — WPF-specific
- `System.Resources` (for `ResourceManager`)
- `System.Globalization` (for `CultureInfo`)
- `System.CodeDom.Compiler`, `System.Diagnostics`, `System.Runtime.CompilerServices`, `System.ComponentModel` (for generated attributes)
### What depends on this module:
- **Inferred**: XAML files within the `GroupChannelList` module that use the `{local:Translate KeyName}` markup extension syntax for localized UI strings.
- **Inferred**: Code-behind files that reference `StringResources` properties directly (though the class is `internal`, limiting this to within the assembly).
---
## 5. Gotchas
1. **Missing key indicator**: When a resource key is not found, the returned string includes the key name appended (e.g., `#stringnotfound# MyMissingKey`). This is useful for debugging but may appear in production UI if resources are missing.
2. **Null/empty key handling**: Passing `null` or empty string to `TranslateExtension` constructor returns only `#stringnotfound#` without a key suffix, making it impossible to distinguish which empty/null key caused the issue.
3. **Auto-generated file warning**: `StringResources.Designer.cs` is regenerated from a `.resx` file. Developers should not edit this file directly; instead, modify the underlying `.resx` file and regenerate.
4. **Culture not explicitly set**: The `TranslateExtension.ProvideValue` method does not explicitly pass a `CultureInfo` to `GetString()`. It relies on `StringResources.ResourceManager.GetString(key)` which uses the current UI culture. If `StringResources.Culture` is set, it must be done separately; the markup extension does not interact with it.
5. **Internal visibility limitation**: `StringResources` is `internal`, meaning direct programmatic access to resource strings is restricted to within the `GroupChannelList.Resources` namespace/assembly. External consumers must use `TranslateExtension` in XAML or use reflection.

View File

@@ -0,0 +1,100 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/View/GroupChannelListView.xaml.cs
generated_at: "2026-04-17T15:58:43.555476+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "d3939bb26e2af959"
---
# GroupChannelListView Documentation
## 1. Purpose
`GroupChannelListView` is a WPF UserControl (code-behind) that provides the view layer for displaying and managing a list of group channels in a tabular format. It handles user interactions including drag-and-drop sensor/hardware assignment, channel reordering, column visibility management based on view modes, and navigation events. This view implements `IGroupChannelListView` and serves as the UI component within the Groups module for configuring channel assignments in test setups and group configurations.
## 2. Public Interface
### Properties
| Signature | Description |
|-----------|-------------|
| `bool ReadOnlyChannelsMode { get; }` | Returns whether user input controls should be read-only. Delegates to `IGroupChannelListViewModel.ReadOnlyChannelsMode` if DataContext is valid; otherwise returns `false`. |
### Methods
| Signature | Description |
|-----------|-------------|
| `void HandleColumns(IsoViewMode viewMode)` | Dynamically configures column visibility based on the specified `IsoViewMode`. Manages Group, ISO Code, User Code, Dallas ID, and Test Setup Order columns. Reads global setting "ShowGroups" to determine group column visibility. |
### Constructor
| Signature | Description |
|-----------|-------------|
| `GroupChannelListView()` | Initializes the component and subscribes to `ListViewStatusEvent` via `IEventAggregator` to handle scroll-to-bottom requests. |
### Event Handlers (Private, wired to XAML)
| Method | Trigger | Behavior |
|--------|---------|----------|
| `Clear_Click(object sender, RoutedEventArgs e)` | Clear button click | Calls `viewModel.Clear(channel)` and `viewModel.NotifyChannelsChanged()` for the affected `IGroupChannel`. |
| `Delete_Click(object sender, RoutedEventArgs e)` | Delete button click | Publishes `GroupChannelDeleteRequestEvent` with `GroupChannelDeleteRequestEventArgs`. Special handling for blank channels with order values (bug fix 14546). |
| `MoveTop_Click`, `MoveUp_Click`, `MoveDown_Click`, `MoveBottom_Click` | Move button clicks | Calls corresponding `vm.MoveTop()`, `vm.MoveUp()`, `vm.MoveDown()`, `vm.MoveBottom()` methods. Supports multi-selection via `GetSelectedChannelsOrdered()`. |
| `ChannelList_Drop(object sender, DragEventArgs e)` | Drop operation | Handles `DragAndDropPayload.FORMAT` for sensor assignment and `DTS.Common.Classes.Hardware.DragAndDropPayload.FORMAT` for hardware assignment via `vm.DoSensorAssignment()` and `vm.DoHardwareAssignment()`. |
| `TextBox_Drop(object sender, DragEventArgs e)` | Drop on text box | Same drop handling as `ChannelList_Drop`, but extracts `IGroupChannel` from `Control.DataContext` or `TextBlock.DataContext`. |
| `ChannelCodeBuilder_OnChannelCodeSelected(object sender, string code, string name, ChannelEnumsAndConstants.ChannelCodeType codeType)` | Channel code selection | Sets `IsoCode`/`IsoChannelName` or `UserCode`/`UserChannelName` based on `codeType`. Calls `viewModel.MarkModified(channel)`. |
| `ChannelNameBuilder_OnChannelCodeSelected(...)` | Channel name selection | Similar to above but sets name first, then code. |
| `ISOCode_LostFocus(object sender, RoutedEventArgs e)` | ISO Code field loses focus | If `UseISOCodeFilterMapping` is true, retrieves software filters and calls `channel.GetFilterClassFromISOCode()` to set `FilterClass`. |
| `Hyperlink_Click(object sender, RoutedEventArgs e)` | Hyperlink click | Publishes `PageNavigationRequestEvent` with destination `Sensor` for navigation. |
## 3. Invariants
- **DataContext Contract**: Most operations assume `DataContext` is either `IGroupChannelListViewModel` or `GroupChannelListViewModel`. Operations silently return if this contract is violated.
- **Column Management**: `ChannelListListView.View` must be of type `DTS.Common.Controls.AutoSizedGridView` for column manipulation methods to function.
- **Drag-Drop Payload Formats**: The view recognizes specific format strings:
- `DragAndDropPayload.FORMAT` and `DragAndDropPayload.ALT_FORMAT` for sensor payloads
- `DTS.Common.Classes.Hardware.DragAndDropPayload.FORMAT` for hardware payloads
- **Selection Ordering**: `GetSelectedChannelsOrdered()` returns channels sorted by their index in `ChannelListListView.Items`, preserving visual order.
- **Order Column Exclusivity**: Either `TestSetupOrderColumn` or `GroupOrderColumn` is displayed at index 0, never both simultaneously.
## 4. Dependencies
### Imports (This module depends on)
| Namespace | Purpose |
|-----------|---------|
| `DTS.Common.Classes.Groups` | `GroupChannel` entity |
| `DTS.Common.Classes.Sensors.SensorsList` | Sensor-related types |
| `DTS.Common.Controls` | `AutoSizedGridView`, `GridViewColumnHeaderSearchable` |
| `DTS.Common.Enums` | `IsoViewMode` enum |
| `DTS.Common.Enums.Channels` | `ChannelEnumsAndConstants` |
| `DTS.Common.Events` | `PageNavigationRequestEvent`, `PageNavigationRequest` |
| `DTS.Common.Events.Groups.GroupChannelList` | `ListViewStatusEvent`, `ListViewStatusArg`, `GroupChannelDeleteRequestEvent`, `GroupChannelDeleteRequestEventArgs` |
| `DTS.Common.Interface.Channels` | `IHardwareChannel` |
| `DTS.Common.Interface.DataRecorders` | Data recorder interfaces |
| `DTS.Common.Interface.Groups.GroupChannelList` | `IGroupChannelListView`, `IGroupChannelListViewModel`, `IGroupChannel` |
| `DTS.Common.Settings` | `SettingsDB.GetGlobalValueBool()` |
| `DTS.Common.Utils` | `MouseUtilities` for drag-drop coordinate handling |
| `Prism.Ioc` | `ContainerLocator` for service resolution |
| `Prism.Events` | `IEventAggregator` for pub/sub messaging |
| `DTS.SensorDB` | `SoftwareFilter.GetSoftwareFilters()` (referenced in `ISOCode_LostFocus`) |
### Known Dependents
Not determinable from this source file alone.
## 5. Gotchas
1. **Drag-Drop Mouse Position**: The code explicitly uses `MouseUtilities.GetMousePosition(target)` instead of standard WPF mechanisms because "during a drag-drop operation, the WPF mechanisms for getting the coordinates behave strangely."
2. **Blank Channel Deletion (Bug 14546)**: Blank channels may still have `TestSetupOrder` or `GroupChannelOrder` assigned. The delete logic allows deletion of blank channels only if their order value is greater than 0, depending on `UseTestSetupOrder` mode.
3. **Modifier Key Format Mutation**: During drag operations, the code mutates format strings by prepending `"ALT_"` or `"CTRL_"` based on `DragDropKeyStates`. This creates format strings like `"ALT_FORMAT"` that must match expected payload constants.
4. **Inconsistent Drag-Over Behavior**: `ChannelList_DragOver` allows `DragAndDropPayload.ALT_FORMAT` but `TextBox_DragOver` handles it differently—some formats that are allowed in list-level drag-over are rejected in text-box drag-over.
5. **Hardcoded Column Dependencies**: `AddDallasIdColumn()` relies on `HardwareColumn` existing to determine insertion index. If `HardwareColumn` is not in the view, the insertion logic may fail or insert at an unexpected position.
6. **Empty Event Handler**: `ChannelListListView_SelectionChanged` is wired but contains no implementation.
7. **Global Setting Dependency**: `HandleColumns` reads `"ShowGroups"` global setting via `SettingsDB.GetGlobalValueBool()` with default `true`. This creates implicit runtime configuration dependency.

View File

@@ -0,0 +1,111 @@
---
source_files:
- DataPRO/Modules/Groups/GroupChannelList/ViewModel/GroupChannelListViewModel.cs
generated_at: "2026-04-17T16:01:14.282913+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "593e1e1e445f103d"
---
# GroupChannelListViewModel Documentation
## 1. Purpose
The `GroupChannelListViewModel` class serves as the presentation logic layer for managing channel configurations within Groups and Test Setups in a data acquisition system. It orchestrates the assignment of sensors and hardware channels, handles text parsing for bulk channel creation, manages filtering and sorting of channel lists, and coordinates UI interactions through Prism's event aggregation system. The class supports both Group-based channel management and Test Setup ordering modes, providing bidirectional synchronization between channel properties and underlying data models.
## 2. Public Interface
### Properties
| Signature | Description |
|-----------|-------------|
| `IGroupChannelListView View { get; set; }` | The associated view instance. |
| `IGroupChannelSettingsListView SettingsView { get; set; }` | The settings view instance. |
| `InteractionRequest<Notification> NotificationRequest { get; }` | Interaction request for displaying notifications. |
| `InteractionRequest<Confirmation> ConfirmationRequest { get; }` | Interaction request for displaying confirmations. |
| `bool SettingsViewLoaded { get; set; }` | Indicates whether the SettingsView has loaded. |
| `bool SettingChannelsLoaded { get; set; }` | Indicates whether SettingChannel UI elements were created. |
| `event PropertyChangedEventHandler PropertyChanged` | Property change notification event. |
### Methods
| Signature | Description |
|-----------|-------------|
| `void OnPropertyChanged(string propertyName)` | Raises `PropertyChanged` event; publishes `GroupChannelsChangedEvent` when `ChannelCount` changes. |
| `void UpdateRangeLowG(IGroupChannel channelChanged)` | Updates all Low G channels on the same DAS to match the range of the changed channel. |
| `void UpdateRangeARS(IGroupChannel channelChanged)` | Updates all ARS channels on the same DAS to match the range of the changed channel. |
| `void UpdateACCouplingEnabled(IGroupChannel channelChanged)` | Propagates AC coupling enabled state to other channels on the same DAS. |
| `IGroup CreateGroupIfNeeded(ITestSetup testSetup, string groupName)` | Creates a group if it doesn't exist; delegates to `GroupList.Model.Group.CreateGroupIfNeeded`. |
| `void DoSensorAssignment(IGroupChannel groupChannel, IDragAndDropItem[] sensors)` | Assigns sensors to channels starting at the specified channel index. Refuses assignment to TSR AIR channels (non-StreamOut/non-Uart). |
| `void DoHardwareAssignment(IGroupChannel groupChannel, IHardwareChannel[] hardwareChannels)` | Assigns hardware channels starting at the specified index. TSR AIR hardware has special restrictions. |
| `void Unset()` | Clears all channels, dictionaries, and filters; resets view state. |
| `void ClearAllFilters()` | Resets search term, bridge filter, and field filters; publishes `ListViewStatusEvent`. |
| `void OnSetActive()` | Refreshes channel state, column visibility, and UI bindings when the view becomes active. |
| `bool CompareAndMarkChannelParameters(IGroupChannel ch)` | Compares channel parameters against sensor database values; marks differences for UI decoration. |
| `IDictionary<IGroup, IGroupChannel[]> PopulateChannels(object page, IDictionary<int, ISensorData> sensorLookup, IDictionary<int, IDASHardware> hardwareLookup, IChannelSetting[] channelDefaults, bool allowChannelDeletionByNonAdminUser = true, bool userIsAdmin = true, bool allowSensorPushAndPull = false, bool keepExistingChannels = false, bool allowChannelDeletionFromFixedGroup = false)` | Populates channel lists from sensor and hardware lookups; handles TSR AIR embedded sensors and fixed group constraints. |
| `void Cleanup()` | Empty cleanup method. |
| `Task CleanupAsync()` | Returns `Task.CompletedTask`. |
| `void Initialize()`, `void Initialize(object parameter)`, `void Initialize(object parameter, object model)` | Empty initialization methods. |
| `Task InitializeAsync()`, `Task InitializeAsync(object parameter)` | Return `Task.CompletedTask`. |
| `void Activated()` | Empty activation method. |
| `void ReportErrors(string[] errors)` | Publishes `PageErrorEvent` with provided errors. |
| `void GroupNameChanged(IGroupChannel channel)` | Handles group name changes in Test Setup mode; removes channel from old group, creates new group if needed. |
| `void MarkModified(IGroupChannel channel, bool bNotifyChanged = true)` | Marks a channel as modified; adds a new blank channel if modifying the last one. |
| `void NotifyChannelsChanged()` | Publishes `PageModifiedEvent` and `GroupUpdatedEvent`; raises property change for counts. |
| `void Clear(IGroupChannel channel)` | Clears the specified channel's data. |
| `void Remove(IGroupChannel channel, bool notifyChanged = true)` | Removes a channel from the list; handles Test Setup group cleanup. |
## 3. Invariants
1. **Blank Channel at End**: `AllChannels` and `Channels` collections always contain a blank `GroupChannel` at the end, used for adding new channels via `MarkModified`.
2. **TSR AIR Channel Restrictions**: Channels with `HardwareChannel.IsTSRAIR == true` (excluding StreamOut and Uart types) cannot have sensors or hardware reassigned via drag-and-drop.
3. **Channel Ordering**: Channels maintain either `TestSetupOrder` or `GroupChannelOrder` (1-indexed), determined by `UseTestSetupOrder` property.
4. **ISO Code Length**: ISO codes are truncated to 16 characters maximum in `ParseText`.
5. **Move Button State**: The first channel has `CanMoveUp = false`; the last non-blank channel has `CanMoveDown = false`.
6. **Filter Preservation**: Channels in `_dontFilterList` are excluded from filtering operations to maintain visibility during editing.
7. **Fixed Group Deletion**: When `AllowChannelDeletionFromFixedGroup = false`, channels with non-null `StaticGroupId` have `DeleteShouldBeEnabled = false`.
## 4. Dependencies
### This Module Depends On:
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `Delegate` commands, `InteractionRequest`
- **Unity Container**: `IUnityContainer` for service resolution
- **DTS.Common.Classes.Groups**: `Group` model class
- **DTS.Common.Enums**: `HardwareTypes`, `PossibleFilters`, `Fields`, sensor enums
- **DTS.Common.Events**: `GroupChannelsChangedEvent`, `RaiseNotification`, `BusyIndicatorChangeNotification`, `TextPastedEvent`, `PageErrorEvent`, `PageModifiedEvent`, `GroupUpdatedEvent`, `AppStatusEvent`, `ListViewStatusEvent`
- **DTS.Common.Interface.Channels**: `IHardwareChannel`, `IChannelCode`, `IChannelSetting`
- **DTS.Common.Interface.Groups.GroupChannelList**: `IGroupChannelListView`, `IGroupChannelSettingsListView`, `IGroupChannel`
- **DTS.Common.Interface.Sensors**: `ISensorData`, `IDragAndDropItem`
- **DTS.Common.Storage**: `DbOperations` for channel setting defaults
- **DTS.Common.Constants**: `TDAS_TOM_DIGITAL_OUT_DURATION_MAX`
- **System.ComponentModel.Composition**: `[PartCreationPolicy(CreationPolicy.Shared)]` for MEF
### Events Consumed:
- `RaiseNotification``OnRaiseNotification`
- `BusyIndicatorChangeNotification``OnBusyIndicatorNotification`
- `TextPastedEvent``OnTextPasted`
### Events Published:
- `GroupChannelsChangedEvent`, `PageErrorEvent`, `PageModifiedEvent`, `GroupUpdatedEvent`, `AppStatusEvent`, `ListViewStatusEvent`
## 5. Gotchas
1. **TSR AIR Embedded Sensors**: The `PopulateChannels` method contains special logic to handle embedded sensors in TSR-AIR units, only adding them if the unit isn't already represented in the group. This logic is spread across multiple checks and can be difficult to follow.
2. **Sensor Serial Number Parsing**: `GetSensorSerialNumber` handles sensors with names in format `"Name (SerialNumber)"` vs. just `"SerialNumber"`. The dictionary lookup depends on this parsing being consistent.
3. **Blank Channel Management**: The blank channel at the end of lists is both a UI affordance and a state management mechanism. Removing or modifying it triggers creation of a new blank channel, which can cause unexpected list changes.
4. **Test Setup vs. Group Mode**: Many methods check `UseTestSetupOrder` to determine behavior. The same ViewModel serves both contexts, and some operations (like `GroupNameChanged`) are no-ops in Group mode.
5. **Filter State Persistence**: `_dontFilterList` is cleared on user-initiated filter operations but preserved during programmatic filtering. This can lead to unexpected channel visibility if not managed carefully.
6. **Digital Out Duration Max**: TDAS TOM hardware has a hardcoded max value (`TDAS_TOM_DIGITAL_OUT_DURATION_MAX`) applied in `ResetSettingChannels`, separate from other channel validation.
7. **Sensor Push/Pull**: The `AllowSensorPushAndPull` flag affects whether channel parameters are compared against sensor database values and whether `BorderShouldShowOutOfDate` is set. This feature appears to be for highlighting parameter drift from sensor defaults.

View File

@@ -0,0 +1,31 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/GroupImportModule.cs
generated_at: "2026-04-17T16:15:12.801021+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "64c3568f982b9a92"
---
# GroupImport
### Purpose
This module is a Prism-based plugin module that provides group import functionality to the main application. It registers views and view models for group import operations (import view, options view, preview view) with the Unity dependency injection container, enabling the application to display and manage group import workflows.
### Public Interface
- **`GroupImportModule`** (class, implements `IModule`)
- `public GroupImportModule(IUnityContainer unityContainer)` - Constructor accepting a Unity container via dependency injection.
- `public void Initialize()` - Registers the following types with the Unity container:
- `IGroupImportImportView``GroupImportImportView`
- `IGroupImportOptionsView``GroupImportOptionsView`
- `IGroupImportPreviewView``GroupImportPreviewView`
- `IGroupImportViewModel``GroupImportViewModel`
- `public void OnInitialized(IContainerProvider containerProvider)` - Empty implementation.
- `public void RegisterTypes(IContainerRegistry containerRegistry)` - Calls `Initialize()`.
- **`GroupImageAttribute`** (class, extends `ImageAttribute`)
- `public override BitmapImage AssemblyImage` - Returns an image loaded via `AssemblyInfo.GetImage(AssemblyNames.GroupImport.ToString())`.
- `public override string AssemblyName` - Returns `AssemblyNames.GroupImport.ToString()`.
- `public override string AssemblyGroup` - Returns `eAssemblyGroups.Prepare.ToString()`.
- `public override eAssemblyRegion AssemblyRegion` - Throws `NotImplementedException

View File

@@ -0,0 +1,13 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/Properties/AssemblyInfo.cs
generated_at: "2026-04-17T16:47:44.902525+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "60b8a2e7063ea2af"
---
# Documentation: GroupImportModule Assembly Configuration
## 1. Purpose
This source file, `AssemblyInfo.cs`, serves as the assembly manifest configuration for the `GroupImportModule` component within the DataPRO system. Its

View File

@@ -0,0 +1,68 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupImport/Resources/StringResources.Designer.cs
generated_at: "2026-04-17T15:58:05.941398+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "649541a3a7393158"
---
# Documentation: GroupImport Resources Module
## 1. Purpose
This module provides localization infrastructure for the Group Import feature in DataPRO. It consists of a WPF markup extension (`TranslateExtension`) enabling XAML-based string resource lookup, and an auto-generated strongly-typed resource class (`StringResources`) containing localized strings for TDAS group file import operations, validation messages, preview UI labels, and error/warning text. The module supports the import workflow from file selection through validation to completion.
---
## 2. Public Interface
### `TranslateExtension` (Class)
**Namespace:** `DBImportExport.Resources`
**Attribute:** `[MarkupExtensionReturnType(typeof(string))]`
A WPF markup extension for retrieving localized strings in XAML bindings.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `TranslateExtension(string key)` | Initializes the extension with the resource key to look up. |
| `ProvideValue` | `override object ProvideValue(IServiceProvider serviceProvider)` | Returns the localized string for `_key`, or a fallback indicator if not found. |
| `NotFound` | `const string = "#stringnotfound#"` | Constant returned when the key is null, empty, or the resource is missing. |
**Behavior of `ProvideValue`:**
- Returns `NotFound` if `_key` is null or empty.
- Returns `StringResources.ResourceManager.GetString(_key)` if the key exists.
- Returns `NotFound + " " + _key` if the key is not found in the resource manifest.
---
### `StringResources` (Class)
**Namespace:** `GroupImport.Resources`
**Modifiers:** `internal`, `sealed` (implied by auto-generation)
A strongly-typed resource class auto-generated by `StronglyTypedResourceBuilder`. Provides access to localized strings via static properties.
| Member | Type | Description |
|--------|------|-------------|
| `ResourceManager` | `static ResourceManager` | Returns the cached `ResourceManager` instance for this assembly. Lazy-initialized. |
| `Culture` | `static CultureInfo` | Gets/sets the current UI culture for resource lookups. |
**Resource String Properties (static, read-only):**
| Property | Default Value (from comments) | Context |
|----------|-------------------------------|---------|
| `GroupTags` | "Group Tag(s): " | Label for group tags display |
| `Import_Importing` | "Importing {0}:{1}" | Import progress message (format string) |
| `ImportFileFilter` | "TDAS group file (*.grp)\|*.grp\|All Files (*.*)\|*.*" | File dialog filter |
| `Importing_Done` | "Done" | Import completion status |
| `None` | "(None)" | Null/empty placeholder |
| `Options_Browse` | "Browse" | Browse button label |
| `Options_Files` | "File(s)" | Files label |
| `Options_Format` | "Format" | Format label |
| `Preview_CompleteGroupChannels` | "Channels that will be imported" | Preview section header |
| `Preview_EmptyFile` | "Empty file" | Empty file warning |
| `Preview_Groups` | "Groups" | Groups label |
| `Preview_IncompleteGroupChannels` | "Channels that will not be imported" | Preview section header |
| `Preview_InvalidFullScaleCapacity` | "Invalid full scale capacity" | Validation error |
| `Preview_InvalidFullScaleInput` | "Invalid desired range for {0}::{1}, the sensor capacity will be used instead." | Validation warning (format string)

View File

@@ -0,0 +1,54 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/View/GroupImportImportView.xaml.cs
- DataPRO/Modules/Groups/GroupImport/View/GroupImportOptionsView.xaml.cs
- DataPRO/Modules/Groups/GroupImport/View/GroupImportPreviewView.xaml.cs
generated_at: "2026-04-17T15:55:09.583371+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "6791e57197b8d508"
---
# Documentation: GroupImport Views
## 1. Purpose
This module provides the WPF view components for a Group Import wizard workflow. It contains three views—`GroupImportImportView`, `GroupImportOptionsView`, and `GroupImportPreviewView`—that implement interfaces from `DTS.Common.Interface.Groups` and handle user interaction for importing groups from files. The views serve as the UI layer, delegating business logic to `GroupImportViewModel` and validating user input before allowing progression through the wizard steps.
---
## 2. Public Interface
### GroupImportImportView
**Signature:** `public partial class GroupImportImportView : IGroupImportImportView`
| Member | Description |
|--------|-------------|
| `GroupImportImportView()` | Constructor. Calls `InitializeComponent()` to load the XAML-defined UI. |
---
### GroupImportOptionsView
**Signature:** `public partial class GroupImportOptionsView : IGroupImportOptionsView`
| Member | Description |
|--------|-------------|
| `GroupImportOptionsView()` | Constructor. Calls `InitializeComponent()` to load the XAML-defined UI. |
| `bool Validate(out List<string> errors, out List<string> warnings)` | Validates whether the user can proceed to the preview step. Returns `true` if at least one file is selected (`vm.SourceFiles.Length >= 1`); otherwise, adds `StringResources.Preview_NoFilesSelected` to errors and returns `false`. |
---
### GroupImportPreviewView
**Signature:** `public partial class GroupImportPreviewView : IGroupImportPreviewView`
| Member | Description |
|--------|-------------|
| `GroupImportPreviewView()` | Constructor. Calls `InitializeComponent()` to load the XAML-defined UI. |
| `void GroupName_Changed(object sender, TextChangedEventArgs e)` | Private event handler. Updates `group.GroupName` from the TextBox, calls `ch.GroupNameInvalidate()` on all channels, and invokes `vm.CheckGroupName()`. |
| `void GroupTags_Changed(object sender, TextChangedEventArgs e)` | Private event handler. Updates `group.GroupTags` from the TextBox. |
| `void IncludedChecked(object sender, RoutedEventArgs e)` | Private event handler. Calls `vm.InvalidateChannels()` when a group's included checkbox is checked. |
| `void IncludedUnchecked(object sender, RoutedEventArgs e)` | Private event handler. Calls `vm.InvalidateChannels()` when a group's included checkbox is unchecked. |
| `bool Validate(bool userIsAdmin, out List<string> errors, out List<string> warnings)` | Public validation method. Checks group and channel validity for import. Returns `true` if valid to proceed. See detailed behavior below

View File

@@ -0,0 +1,98 @@
---
source_files:
- DataPRO/Modules/Groups/GroupImport/ViewModel/GroupImportViewModel.cs
generated_at: "2026-04-17T16:01:00.422137+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ea98f9d39127a201"
---
# GroupImportViewModel Documentation
## 1. Purpose
`GroupImportViewModel` is the ViewModel responsible for importing Groups and TestObjects from `.grp` files in a WPF/Prism-based application. It orchestrates the complete import workflow: file browsing, parsing source files into group/channel structures, validating data, previewing import contents, and executing the import on a background thread. The class implements `IGroupImportViewModel` and serves as the data context for three views (`IGroupImportOptionsView`, `IGroupImportPreviewView`, `IGroupImportImportView`).
---
## 2. Public Interface
### Constructor
```csharp
public GroupImportViewModel(
IGroupImportOptionsView optionsView,
IGroupImportPreviewView previewView,
IGroupImportImportView importView,
IRegionManager regionManager,
IEventAggregator eventAggregator,
IUnityContainer unityContainer)
```
Initializes the ViewModel, wires up view DataContexts, creates interaction requests, and subscribes to `RaiseNotification` and `BusyIndicatorChangeNotification` events.
### Public Methods
| Method | Signature | Description |
|--------|-----------|-------------|
| `ParseSourceFiles` | `void ParseSourceFiles(string userTags)` | Reads `.grp` files from `SourceFiles`, parsing groups and channels. Populates `Groups` and `Channels` arrays. |
| `Import` | `void Import()` | Queues the import operation on a background thread via `ThreadPool.QueueUserWorkItem`. |
| `SetStatus` | `void SetStatus(string message, Color color)` | Updates `ImportProgressColor`, hides progress bar, sets `ImportProgressText`, and invokes `EnableUI`. |
| `Reset` | `void Reset()` | Re-initializes the ViewModel to default state (clears `SourceFiles`, `Channels`, `Groups`, resets progress UI). |
| `CheckGroupName` | `void CheckGroupName()` | Validates group names for duplicates within the import and against existing groups (if `Overwrite` is false). Sets `GroupNameHasError` on each group. |
| `OnPropertyChanged` | `void OnPropertyChanged(string propertyName)` | Raises the `PropertyChanged` event. |
| `InvalidateChannels` | `void InvalidateChannels()` | Raises PropertyChanged for `IncompleteChannels` and `CompleteChannels`. |
| `Cleanup` | `void Cleanup()` | Empty implementation. |
| `CleanupAsync` | `Task CleanupAsync()` | Returns `Task.CompletedTask`. |
| `Initialize` | `void Initialize()` / `void Initialize(object parameter)` / `void Initialize(object parameter, object model)` | Empty implementations. |
| `InitializeAsync` | `Task InitializeAsync()` / `Task InitializeAsync(object parameter)` | Return `Task.CompletedTask`. |
| `Activated` | `void Activated()` | Empty implementation. |
### Commands
| Property | Type | Description |
|----------|------|-------------|
| `ImportBrowseCommand` | `DelegateCommand` | Opens an `OpenFileDialog` for selecting `.grp` files. Sets `SourceFiles` and `BrowseOk`, then invokes `SwitchNavSteps` with `Preview` step. |
### Public Properties
| Property | Type | Description |
|----------|------|-------------|
| `ImportOptionsView` | `IGroupImportOptionsView` | The options view instance. |
| `ImportPreviewView` | `IGroupImportPreviewView` | The preview view instance. |
| `ImportView` | `IGroupImportImportView` | The import view instance. |
| `NotificationRequest` | `InteractionRequest<Notification>` | Interaction request for notifications. |
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Interaction request for confirmations. |
| `IsDirty` | `bool` | Always returns `false` (private setter never called). |
| `IsBusy` | `bool` | Bound to `BusyIndicatorChangeNotification` event. |
| `IsMenuIncluded` | `bool` | Menu inclusion flag. |
| `IsNavigationIncluded` | `bool` | Navigation inclusion flag. |
| `HeaderInfo` | `string` | Returns `"MainRegion"`. |
| `ImportProgressText` | `string` | Status text for import progress bar. |
| `ImportProgressColor` | `Color` | Color of the import progress bar. |
| `ImportProgressBarVisibility` | `Visibility` | Controls progress bar visibility. |
| `ImportProgressValue` | `double` | Percentage complete of import process. |
| `SourceFiles` | `string[]` | Array of `.grp` file paths to parse. Initialized to empty array. |
| `BrowseOk` | `bool` | Indicates if file browse completed successfully. Default `false`. |
| `Groups` | `GroupGRPImportGroup[]` | All parsed groups. Initialized to empty array. |
| `Channels` | `GroupGRPImportChannel[]` | All channels from all groups. Setter calls `InvalidateChannels()`. |
| `IncompleteChannels` | `GroupGRPImportChannel[]` | Computed: channels that will NOT be imported (errors other than `InvalidFullScaleInput` or `InvalidInvertInput`). |
| `CompleteChannels` | `GroupGRPImportChannel[]` | Computed: channels that WILL be imported (no error, or only `InvalidFullScaleInput`/`InvalidInvertInput`). |
| `Logger` | `FileUtils.LogDelegate` | Logging facility. If `null`, no logging occurs. |
| `SwitchNavSteps` | `SwitchNavStepsDelegate` | Command for switching navigation steps. |
| `CheckGroupExists` | `CheckGroupExistsDelegate` | Command to check if a group exists in the application. |
| `CheckSensorExists` | `CheckSensorExistsDelegate` | Command to check if a sensor exists. |
| `CreateGroup` | `CreateGroupDelegate` | Command to create a group. |
| `AddChannel` | `AddChannelToGroupDelegate` | Command to add a channel to a group. |
| `CommitGroups` | `CommitGroupsDelegate` | Command to commit groups to the database. |
| `DisableUI` | `Disable_UIDelegate` | Command to disable the UI during import. |
| `EnableUI` | `Enable_UIDelegate` | Command to enable the UI after import. |
### Events
```csharp
public event PropertyChangedEventHandler PropertyChanged;
```
---
## 3. Invariants
- **File Format**: `.grp` files

View File

@@ -0,0 +1,36 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/GroupListModule.cs
generated_at: "2026-04-17T16:46:55.033658+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "4ac5a94ee419c4b2"
---
# Documentation: GroupListModule
## 1. Purpose
The `GroupListModule` is a Prism module responsible for registering the Group List feature's view and view-model with the Unity dependency injection container. It provides assembly-level metadata (name, image, group, and region) that enables the main application shell to discover and display this module as an available component. The module belongs to the "Prepare" assembly group and targets the `GroupListRegion` for UI composition.
---
## 2. Public Interface
### `GroupListModule` (Class)
Implements `Prism.Modularity.IModule`. The primary module entry point for the Group List feature.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GroupListModule(IUnityContainer unityContainer)` | Accepts a Unity container via dependency injection and stores it in `_unityContainer`. |
| `Initialize` | `void Initialize()` | Registers `IGroupListView``GroupListView` and `IGroupListViewModel``GroupListViewModel` with the Unity container. |
| `OnInitialized` | `void OnInitialized(IContainerProvider containerProvider)` | Empty implementation (no post-initialization logic). |
| `RegisterTypes` | `void RegisterTypes(IContainerRegistry containerRegistry)` | Delegates to `Initialize()`. |
### `GroupListModuleNameAttribute` (Class)
Extends `TextAttribute`. Assembly-level attribute providing the module's name.
| Member | Signature | Description |
|--------|-----------|-------------|
| Constructor | `GroupListModuleNameAttribute()` | Default constructor; sets `AssemblyName` to `AssemblyNames.GroupList.ToString()`. |
| Constructor | `GroupListModuleNameAttribute(string s)` | Overload accepting a string parameter (

View File

@@ -0,0 +1,16 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Model/ChannelSetting.cs
generated_at: "2026-04-17T16:47:02.302066+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "e3fe02109fc0ecbe"
---
# Documentation for ChannelSetting.cs
## 1. Purpose
This file is intended to define a model within the `GroupList.Model` namespace, likely representing configuration or settings for a channel. However, the provided source code contains only an empty namespace definition and an unused import. The actual implementation of the `ChannelSetting` type is missing from the file.
## 2. Public Interface
**None.** The namespace `GroupList.Model` is empty in the provided source. No classes, structs, interfaces

View File

@@ -0,0 +1,34 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Properties/Settings.Designer.cs
- DataPRO/Modules/Groups/GroupList/Properties/AssemblyInfo.cs
generated_at: "2026-04-17T16:28:16.255702+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "5576497584da23f4"
---
# Properties
### Purpose
This module contains auto-generated build artifacts for the `GroupTemplateList` assembly, including application settings infrastructure and assembly metadata. It provides the standard .NET Settings singleton pattern for persisting user or application configuration scoped to the GroupList module, and defines assembly identity attributes used by the CLR for binding and versioning.
### Public Interface
- **`Settings` class** (internal sealed partial) - Inherits from `global::System.Configuration.ApplicationSettingsBase`. Provides strongly-typed access to application settings.
- `public static Settings Default { get; }` - Returns a synchronized singleton instance of the Settings class, lazily initialized via `ApplicationSettingsBase.Synchronized(new Settings())`.
### Invariants
- The `Settings` class is auto-generated by `SettingsSingleFileGenerator` (version 17.10.0.0) and should not be manually edited; changes will be lost on regeneration.
- The `defaultInstance` field is always assigned via `Synchronized()`, ensuring thread-safe access to settings.
- Assembly version is fixed at `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`.
- COM visibility is disabled at the assembly level (`ComVisible(false)`).
### Dependencies
- **Depends on**: `System.Configuration.ApplicationSettingsBase` (from System.Configuration assembly), `System.Runtime.CompilerServices`, `System.CodeDom.Compiler`.
- **Depended on by**: Unclear from source alone; presumably consumed by the parent `GroupList` module for settings access.
### Gotchas
- The assembly title is `"GroupTemplateList"` but the namespace is `GroupList.Properties` — this naming inconsistency may cause confusion when searching for the assembly or namespace.
- The `Settings` class is `internal`, so it cannot be accessed from outside this assembly without friend assembly declarations (`InternalsVisibleTo`).
---

View File

@@ -0,0 +1,35 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/Resources/TranslateExtension.cs
- DataPRO/Modules/Groups/GroupList/Resources/StringResources.Designer.cs
generated_at: "2026-04-17T16:12:38.870054+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "075ddccdc71b15d4"
---
# Resources
### 1. Purpose
This module provides localization infrastructure for the `GroupList` assembly. It contains a XAML markup extension for declarative string lookup and a strongly-typed resource accessor class generated from a `.resx` file. It centralizes UI string management for group-related views (e.g., "AssociatedTestSetups", "Channels", "Description").
### 2. Public Interface
**Class: `TranslateExtension`** (inherits `MarkupExtension`)
* `TranslateExtension(string key)`: Constructor that accepts the resource key to look up.
* `object ProvideValue(IServiceProvider serviceProvider)`: Returns the localized string for the stored `_key`. Returns `#stringnotfound#` if the key is null/empty, or `#stringnotfound# {key}` if the lookup fails.
**Class: `StringResources`** (internal, auto-generated)
* `static ResourceManager ResourceManager`: Gets the cached `ResourceManager` instance for the `GroupList.Resources.StringResources` resource set.
* `static CultureInfo Culture`: Gets or sets the current UI culture for resource lookups.
* `static string AssociatedTestSetups`: Looks up the "AssociatedTestSetups" string.
* `static string Channels`: Looks up the "Channels" string.
* `static string Description`: Looks up the "Description" string.
* `static string LastModified`: Looks up the "LastModified" string.
* `static string LastModifiedBy`: Looks up the "LastModifiedBy" string.
* `static string Name`: Looks up the "Name" string.
* `static string TemplateName`: Looks up the "TemplateName" string.
### 3. Invariants
* `TranslateExtension._key` is immutable after construction (readonly).
* `TranslateExtension` always returns a non-null string; it never throws on missing keys, instead returning a specific error constant.
* `

View File

@@ -0,0 +1,35 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/View/GroupListView.xaml.cs
generated_at: "2026-04-17T16:47:04.094415+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "1c720369523e38e0"
---
# GroupListView Documentation
## 1. Purpose
`GroupListView` is a WPF view component that provides a sortable, filterable list interface for displaying groups. It serves as the code-behind for `GroupListView.xaml` and implements `IGroupListView`. The view handles user interactions—column header clicks for sorting, search input for filtering, and mouse double-clicks for item selection—delegating all business logic to an `IGroupListViewModel` via the `DataContext`.
---
## 2. Public Interface
### `GroupListView()` (Constructor)
**Signature:** `public GroupListView()`
Initializes the view component by calling `InitializeComponent()`, which loads the associated XAML layout.
### `IGroupListView` (Implemented Interface)
The class implements `IGroupListView` from `DTS.Common.Interface.Groups.GroupTemplateList`. The specific interface members are not visible in this source file.
### Private Event Handlers (wired to XAML events)
| Method | Signature | Behavior |
|--------|-----------|----------|
| `ListViewHeader_Click` | `void ListViewHeader_Click(object sender, RoutedEventArgs e)` | Extracts the clicked `GridViewColumnHeader` from `e.OriginalSource`, retrieves `IGroupListViewModel` from the header's `DataContext`, and calls `viewModel.Sort(colHeader.Tag, true)`. |
| `GridViewColumnHeaderSearchable_OnSearch` | `void GridViewColumnHeaderSearchable_OnSearch(object sender, RoutedEventArgs e)` | Extracts search term from `e.OriginalSource` (cast to `string`), retrieves column tag from `sender`, and calls `vm.Filter(columnTag, searchTerm)` on the view model. |
| `GridViewColumnHeader_OnClick` | `void GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)` | Handles sorting for searchable column headers. Retrieves column tag either directly from `sender` or by traversing the visual tree via `Utils.FindChild<GridViewColumnHeaderSearchable>`, then calls `vm.Sort(columnTag, true)`. |
| `MouseDoubleClick` | `void MouseDoubleClick(object sender, MouseButtonEventArgs e)` | Determines which ListView item is under the mouse cursor using hit-testing, validates the index is within bounds, and

View File

@@ -0,0 +1,54 @@
---
source_files:
- DataPRO/Modules/Groups/GroupList/ViewModel/GroupListViewModel.cs
generated_at: "2026-04-17T16:00:47.692641+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "b926e051d9942d3a"
---
# GroupListViewModel Documentation
## 1. Purpose
`GroupListViewModel` is the presentation logic layer for the Group List module in a WPF/Prism-based application. It manages the display, filtering, sorting, and manipulation of group entities. The class serves as a mediator between the `IGroupListView` view and the underlying `Group` model, handling user interactions (selection, double-click editing, filtering), coordinating with the event system for cross-module communication, and enforcing tag-based access control for non-administrator users.
---
## 2. Public Interface
### Methods
| Signature | Description |
|-----------|-------------|
| `void ClearAllFilters()` | Clears all field-based filters by emptying the internal `_filterByField` dictionary. |
| `void MouseDoubleClick(int index)` | Publishes a `GroupListEditGroupEvent` with the group ID when a single group is selected and the index is valid. |
| `void Filter(string term)` | Sets `CurrentSearchTerm` and triggers a sort/refresh operation. |
| `IGroup GetGroup(int? id, bool updateTags = true)` | Retrieves a group by ID. Optionally updates tags from the database. Returns an empty `Group` if not found or if `id < 0`. |
| `IGroup GetGroup(string displayName)` | Retrieves a non-embedded group by display name. Returns `null` if no non-embedded match is found. |
| `IGroup[] GetGroups(int[] ids)` | Returns all groups whose IDs are contained in the provided array. |
| `IGroup[] GetAllGroups()` | Returns all groups from the model layer. |
| `void DeleteGroups(int[] ids)` | Deletes groups by ID, nullifies `StaticGroupId` on related embedded groups, updates `AllGroups`, and re-applies filters. |
| `IGroup CreateGroup()` | Creates a new `Group` instance (marked as new). |
| `IGroup CreateGroup(SqlDataReader reader, List<string> includedHardwareStringList, List<int> dasIdList)` | Creates a `Group` from a SQL data reader. |
| `IGroup CreateGroup(IGroupDbRecord groupRecord, List<string> includedHardwareStringList, List<int> dasIdList)` | Creates a `Group` from a database record object. |
| `IGroup CreateGroup(List<string> includedHardwareStringList)` | Creates a `Group` with specified hardware strings. |
| `void Filter(object tag, string term)` | Parses `tag` as a `GroupFields` enum, updates filter dictionary, and triggers filtering. |
| `void OnSetActive(object page, bool groupTile, object o)` | Initializes the view model when activated. Filters groups by user role and tag compatibility. If `groupTile` is true, loads test setup lists asynchronously. |
| `void Unset()` | Clears all group arrays, filters, and publishes a `ListViewStatusEvent` with `Unloaded` status. |
| `void Sort(object o, bool bColumnClick)` | Sorts `Groups` by the specified field. Toggles sort direction on repeated column clicks. Applies both search term and field-based filters. |
| `void Cleanup()` | Empty implementation. |
| `Task CleanupAsync()` | Returns `Task.CompletedTask`. |
| `void Initialize()` | Empty implementation. |
| `void Initialize(object parameter)` | Empty implementation. |
| `void Initialize(object parameter, object model)` | Empty implementation. |
| `Task InitializeAsync()` | Returns `Task.CompletedTask`. |
| `Task InitializeAsync(object parameter)` | Returns `Task.CompletedTask`. |
| `void Activated()` | Empty implementation. |
| `void OnPropertyChanged(string propertyName)` | Raises the `PropertyChanged` event. |
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `View` | `IGroupListView` | The associated view instance. Set via constructor; `DataContext` is