init
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Converters/BooleanToWidthConverter.cs
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Converters/SensorIdBackgroundConverter.cs
|
||||
generated_at: "2026-04-16T04:46:41.293810+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "b2bc34d167251ea0"
|
||||
---
|
||||
|
||||
# Converters
|
||||
|
||||
## Documentation: `GroupChannelList.Converters` Module
|
||||
|
||||
### 1. Purpose
|
||||
This module provides WPF value converters used for UI data binding in the `GroupChannelList` module. Specifically, it enables conditional presentation logic—converting boolean values to UI properties such as width (for collapsing/expanding UI elements) and background color (for highlighting sensor-related items). These converters facilitate declarative UI behavior in XAML without requiring additional view-model logic.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `BooleanToWidthConverter`
|
||||
- **Namespace**: `GroupChannelList.Converters`
|
||||
- **Type**: `class` implementing `IValueConverter`
|
||||
- **Method**:
|
||||
```csharp
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
```
|
||||
- **Behavior**: Converts a `bool` input to a `double` width.
|
||||
- If `value` is `null`, returns `0`.
|
||||
- If `parameter` is provided and parses successfully as a `double`, uses that value for `true`; otherwise defaults to `double.NaN`.
|
||||
- Returns the parsed width for `true`, and `0` for `false`.
|
||||
- **Example usage in XAML**:
|
||||
```xaml
|
||||
Width="{Binding IsSensorActive, Converter={StaticResource BooleanToWidthConverter}, ConverterParameter=100}"
|
||||
```
|
||||
|
||||
- **Method**:
|
||||
```csharp
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
```
|
||||
- **Behavior**: Always throws `NotImplementedException`. One-way conversion only.
|
||||
|
||||
#### `SensorIdBackgroundConverter`
|
||||
- **Namespace**: `GroupChannelList.Converters`
|
||||
- **Type**: `class` implementing `IValueConverter`
|
||||
- **Field**:
|
||||
```csharp
|
||||
private static SolidColorBrush SensorIdBrush = new SolidColorBrush(Color.FromArgb(0xFF, 0xE3, 0xFB, 0xE1));
|
||||
```
|
||||
- A frozen `SolidColorBrush` with ARGB color `(0xFF, 0xE3, 0xFB, 0xE1)` (light green, #E3FBE1).
|
||||
|
||||
- **Method**:
|
||||
```csharp
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
```
|
||||
- **Behavior**: Converts a `bool` input to a `Brush`.
|
||||
- If `value` is `null`, returns `Brushes.Transparent`.
|
||||
- If `value` is `true`, returns `SensorIdBrush` (frozen for performance).
|
||||
- If `value` is `false`, returns `Brushes.Transparent`.
|
||||
- Any exception during conversion logs the message via `Trace.WriteLine` and returns `Brushes.Transparent`.
|
||||
- **Example usage in XAML**:
|
||||
```xaml
|
||||
Background="{Binding HasSensorId, Converter={StaticResource SensorIdBackgroundConverter}}"
|
||||
```
|
||||
|
||||
- **Method**:
|
||||
```csharp
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
```
|
||||
- **Behavior**: Always throws `NotImplementedException`. One-way conversion only.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- **`BooleanToWidthConverter`**:
|
||||
- Output is always `0` or a `double` (including `double.NaN` if `parameter` parsing fails).
|
||||
- `parameter` is optional; if missing or invalid, `double.NaN` is used for `true`.
|
||||
- No validation on `value` beyond null-checking; non-`bool` values will cause a runtime `InvalidCastException` (not caught).
|
||||
|
||||
- **`SensorIdBackgroundConverter`**:
|
||||
- `SensorIdBrush` is frozen after first use (via `.Freeze()`) to ensure thread-safety and performance.
|
||||
- Output is always a `Brush`; specifically `Brushes.Transparent` or `SensorIdBrush`.
|
||||
- Null or non-`bool` inputs are handled gracefully (return `Brushes.Transparent`), but exceptions during conversion are silently logged.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Dependencies on external frameworks**:
|
||||
- `System.Windows.Data` (WPF `IValueConverter` interface)
|
||||
- `System.Windows.Media` (`SolidColorBrush`, `Brushes`)
|
||||
- `System.Diagnostics` (`Trace`)
|
||||
- `System.Globalization` (`CultureInfo`)
|
||||
|
||||
- **Dependencies on other modules**:
|
||||
- None inferred from source (no internal project references in imports).
|
||||
- Used by XAML views in the `GroupChannelList` module (inferred from namespace path).
|
||||
|
||||
- **Depended upon by**:
|
||||
- XAML UI elements in `DataPRO.Modules.Groups.GroupChannelList` (e.g., `GroupChannelListView.xaml`), where these converters are referenced as static resources.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **`BooleanToWidthConverter`**:
|
||||
- `ConvertBack` is unimplemented—cannot be used in two-way bindings.
|
||||
- `parameter` parsing is silent: invalid values (e.g., `"abc"`) result in `double.NaN` without error.
|
||||
- Non-`bool` inputs (e.g., `null`, `int`, `string`) will throw `InvalidCastException` at runtime (not caught).
|
||||
|
||||
- **`SensorIdBackgroundConverter`**:
|
||||
- `SensorIdBrush` is shared and frozen *after first use*; if frozen prematurely (e.g., before first conversion), subsequent calls are safe but the freeze is redundant.
|
||||
- Exception handling is minimal: only logs to `Trace`, no user-facing error.
|
||||
- Assumes `value` is `bool`; non-`bool` inputs (e.g., `null`, `int`) will throw `InvalidCastException` (not caught).
|
||||
|
||||
- **Both converters**:
|
||||
- One-way only (`ConvertBack` throws `NotImplementedException`).
|
||||
- No support for culture-specific formatting (uses default `CultureInfo` behavior).
|
||||
- No documentation of expected `targetType` constraints (assumes WPF expects `double`/`Brush` outputs).
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Properties/Settings.Designer.cs
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T04:46:44.908575+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "068d1583fe59a4bb"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## Documentation Page: `GroupChannelList.Properties.Settings`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
This module defines a strongly-typed settings class (`GroupChannelList.Properties.Settings`) for the `GroupChannelList` assembly, enabling centralized access to application-level configuration values via the .NET `ApplicationSettingsBase` infrastructure. It exists solely to expose a thread-safe singleton instance (`Default`) for reading (and potentially writing, though not evident here) user- or application-scoped settings—though no actual settings properties are declared in the provided source, indicating either a minimal placeholder or that settings are defined elsewhere (e.g., in `Settings.settings` or `App.config`).
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
The only public API surface exposed is:
|
||||
|
||||
- **`Settings.Default`**
|
||||
- **Type**: `Settings` (a singleton instance)
|
||||
- **Signature**: `public static Settings Default { get; }`
|
||||
- **Behavior**: Returns the synchronized singleton instance of the `Settings` class, derived from `ApplicationSettingsBase`. This instance provides access to configuration properties (though none are visible in the provided source). Thread-safety is ensured via `ApplicationSettingsBase.Synchronized()`.
|
||||
|
||||
> **Note**: No additional public properties, methods, or fields are declared in the `Settings` class within the provided source. All settings (if any) are implicitly inherited from `ApplicationSettingsBase` and defined externally (e.g., in designer-generated or config files not included here).
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
- The `Settings` class is **sealed** and **partial**, with auto-generated code marked with `<auto-generated>` and attributed with `CompilerGeneratedAttribute` and `GeneratedCodeAttribute`.
|
||||
- The `Default` property returns a **synchronized singleton**, implying thread-safe access to settings (via `ApplicationSettingsBase.Synchronized`).
|
||||
- The class resides in the `GroupChannelList.Properties` namespace, consistent with .NET conventions for strongly-typed settings.
|
||||
- No runtime validation or custom logic is present in the provided source—behavior depends entirely on settings defined externally.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
- **Depends on**:
|
||||
- `System.Configuration` (specifically `ApplicationSettingsBase`)
|
||||
- `System.Runtime.CompilerServices` (for `CompilerGeneratedAttribute`)
|
||||
- `System.CodeDom.Compiler` (for `GeneratedCodeAttribute`)
|
||||
- **Depended upon by**:
|
||||
- Other modules in the `DataPRO` solution (e.g., `GroupChannelList` UI or logic layers) that consume `GroupChannelList.Properties.Settings.Default` to read configuration values.
|
||||
- The .NET configuration system (e.g., `App.config` or `user.config` files) that backs the settings properties.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **Settings are not defined here**: The `Settings` class contains no explicit property declarations (e.g., `public string SomeSetting { get; set; }`). Actual settings must be defined in the corresponding `.settings` file (e.g., `Settings.settings`) and regenerated—this file is purely the generated wrapper.
|
||||
- **No write support evident**: While `ApplicationSettingsBase` supports setting values, the provided source does not confirm whether write operations are enabled or used.
|
||||
- **Thread-safety caveat**: The `Synchronized()` wrapper ensures thread-safe *access*, but atomicity of multi-step operations (e.g., read-modify-write) is not guaranteed.
|
||||
- **Versioning risk**: The assembly version is fixed at `1.0.0.0` (both `AssemblyVersion` and `AssemblyFileVersion`), which may complicate upgrades or settings migration if settings evolve.
|
||||
- **Auto-generated warning**: Manual edits to this file will be overwritten on rebuild—settings must be modified via the Visual Studio Settings Designer or `App.config`.
|
||||
|
||||
> **None identified from source alone** beyond the above.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Resources/TranslateExtension.cs
|
||||
- DataPRO/Modules/Groups/GroupChannelList/Resources/StringResources.Designer.cs
|
||||
generated_at: "2026-04-16T04:46:25.212575+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "5dba578a99876d46"
|
||||
---
|
||||
|
||||
# Documentation: `TranslateExtension` Markup Extension
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides a WPF `MarkupExtension` (`TranslateExtension`) that enables localization of UI strings directly in XAML by resolving resource keys against a strongly-typed resource class (`StringResources`). It serves as a bridge between declarative UI markup and localized string resources, allowing developers to bind text content (e.g., labels, tooltips, headers) to culture-sensitive values without writing code-behind. Its role is critical for internationalization of the `GroupChannelList` module, ensuring that user-facing text adapts to the current UI culture.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `TranslateExtension` class
|
||||
|
||||
- **Namespace**: `GroupChannelList`
|
||||
- **Base class**: `System.Windows.Markup.MarkupExtension`
|
||||
- **Attribute**: `[MarkupExtensionReturnType(typeof(string))]`
|
||||
|
||||
#### Constructor
|
||||
```csharp
|
||||
public TranslateExtension(string key)
|
||||
```
|
||||
- **Parameters**:
|
||||
- `key` (`string`): The resource key (e.g., `"ChannelName"`) used to look up a localized string in `StringResources`.
|
||||
- **Behavior**: Stores the key for later resolution during `ProvideValue`.
|
||||
|
||||
#### `ProvideValue` method
|
||||
```csharp
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
```
|
||||
- **Parameters**:
|
||||
- `serviceProvider` (`IServiceProvider`): WPF service provider (unused in current implementation).
|
||||
- **Returns**:
|
||||
- `string`: The localized string if the key exists and is non-null/non-empty; otherwise, one of two fallback values:
|
||||
- If `_key` is `null` or empty → returns `"#stringnotfound#"`
|
||||
- If `StringResources.ResourceManager.GetString(_key)` returns `null` → returns `"#stringnotfound# " + _key` (e.g., `"#stringnotfound# ChannelName"`)
|
||||
- **Behavior**: Performs a culture-aware lookup using `StringResources.ResourceManager.GetString(_key)`.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Key must be a valid resource key**: The `_key` passed to the constructor must match a property name in `StringResources` (e.g., `"ChannelName"`, `"AnalogParameters_Range"`). Mismatched keys will result in the fallback `"#stringnotfound# <key>"` string.
|
||||
- **Null/empty key handling**: If `_key` is `null` or `string.Empty`, the extension *always* returns `"#stringnotfound#"` (no concatenation with key).
|
||||
- **No culture override via extension**: The extension does not expose or support overriding the culture used for lookup; it relies on the current `Thread.CurrentUICulture` via `StringResources.Culture`.
|
||||
- **No side effects**: `ProvideValue` is pure—no state mutation or I/O occurs beyond the resource lookup.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`System.Windows.Markup`**: Required for `MarkupExtension` base class and `MarkupExtensionReturnTypeAttribute`.
|
||||
- **`GroupChannelList.Resources.StringResources`**: Strongly-typed resource class generated from `.resx` files. Relies on:
|
||||
- `System.Resources.ResourceManager`
|
||||
- `System.Globalization.CultureInfo`
|
||||
- **WPF runtime**: Required for `IServiceProvider` and XAML markup extension resolution.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **XAML files in `GroupChannelList` module**: Used via XMLNS (e.g., `xmlns:res="clr-namespace:GroupChannelList"`) to localize UI elements:
|
||||
```xml
|
||||
<TextBlock Text="{res:Translate ChannelName}" />
|
||||
```
|
||||
- **No other modules directly depend on `TranslateExtension`**—it is consumed only via XAML markup.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **No runtime validation of key existence**: If a resource key is misspelled (e.g., `"ChannelNme"` instead of `"ChannelName"`), the extension silently returns `"#stringnotfound# ChannelNme"`, which may appear as visible text in the UI.
|
||||
- **No fallback to default language**: If a key exists in the `.resx` but lacks a translation for the current culture, `ResourceManager.GetString` returns `null`, triggering the fallback string. This may cause inconsistent behavior if translations are incomplete.
|
||||
- **Hardcoded fallback prefix**: The `"#stringnotfound#"` prefix is hardcoded and not configurable. This could conflict with legitimate strings if used as a key.
|
||||
- **No support for parameterized strings**: While `StringResources` includes format strings (e.g., `"Sensor {0} can not be assigned..."`), `TranslateExtension` does not support passing arguments (e.g., `{res:Translate Key, Arg1, Arg2}`). Developers must use `String.Format` manually in code-behind or elsewhere.
|
||||
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits are overwritten. Adding new keys requires updating the `.resx` file and regenerating the class.
|
||||
- **No thread-safety guarantees**: Though `ResourceManager` is thread-safe, the extension itself is stateful (via `_key`), but this is harmless since each usage creates a new instance.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Groups/GroupChannelList/View/GroupChannelListView.xaml.cs
|
||||
generated_at: "2026-04-16T04:46:59.687984+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "a7a7f5755050a82e"
|
||||
---
|
||||
|
||||
# View
|
||||
|
||||
### **Purpose**
|
||||
`GroupChannelListView` is the WPF view implementation for displaying and interacting with a list of channels associated with a test group or test setup. It provides UI controls for channel management—including reordering, deletion, clearing, filtering, and drag-and-drop assignment of sensors and hardware—while dynamically adjusting column visibility and layout based on the current view mode (`IsoViewMode`), group/test context, and global settings (e.g., `ShowGroups`). It acts as the presentation layer for `GroupChannelListViewModel`, synchronizing UI state with the view model via data binding and event-driven interactions.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
The class implements `IGroupChannelListView` (inferred from `partial class GroupChannelListView : IGroupChannelListView`) and exposes the following public members:
|
||||
|
||||
1. **`bool ReadOnlyChannelsMode { get; }`**
|
||||
Returns `true` if user input controls in the channel list should be read-only. Delegates to `IGroupChannelListViewModel.ReadOnlyChannelsMode`, returning `false` if `DataContext` is unset or not a `IGroupChannelListViewModel`.
|
||||
|
||||
2. **`void HandleColumns(IsoViewMode viewMode)`**
|
||||
Dynamically configures the columns of `ChannelListListView` (an `AutoSizedGridView`) based on `viewMode` and global settings (`ShowGroups`, `UseTestSetupOrder`, `ShowDallasIdColumn`). Adds/removes columns for:
|
||||
- Group order (`GroupColumn`, `GroupOrderColumn`)
|
||||
- Test setup order (`TestSetupOrderColumn`)
|
||||
- User code/name (`UserCodeColumn`, `UserChannelNameColumn`)
|
||||
- ISO code/name (`ISOCodeColumn`, `ISOChannelNameColumn`)
|
||||
- Dallas ID (`DallasIdColumn`)
|
||||
Ensures column ordering respects `usingTestSetup` context.
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
The following must hold during operation:
|
||||
|
||||
- **`ChannelListListView` must be initialized before `HandleColumns()` is called**, as all column operations assume `ChannelListListView.View` is an `AutoSizedGridView`.
|
||||
- **`DataContext` must be set to a `GroupChannelListViewModel` (or `IGroupChannelListViewModel`) for most functionality**. If `DataContext` is `null` or of the wrong type, methods silently return (e.g., `OnListViewEvent`, `Clear_Click`, `Delete_Click`, `MoveUp_Click`, etc.).
|
||||
- **Drag-and-drop operations require `e.Data` to be non-null and contain supported formats** (e.g., `DragAndDropPayload.FORMAT`, `DTS.Common.Classes.Hardware.DragAndDropPayload.FORMAT`). Unsupported formats result in `DragDropEffects.None`.
|
||||
- **Channel deletion for blank channels requires valid ordering**:
|
||||
- If `UseTestSetupOrder`, `channel.TestSetupOrder > 0` must hold.
|
||||
- Otherwise, `channel.GroupChannelOrder > 0` must hold.
|
||||
(Per issue #14546 comment in `Delete_Click`.)
|
||||
- **`ReadOnlyChannelsMode` is `false` if `DataContext` is `null` or not a `IGroupChannelListViewModel`**.
|
||||
- **Column insertion/removal preserves ordering**:
|
||||
- `TestSetupOrderColumn`/`GroupOrderColumn` are always first (index `0`).
|
||||
- User/ISO columns are inserted at indices `0` or `1` depending on `usingTestSetup`.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
**Imports/References (from source):**
|
||||
- `DTS.Common.*`: Core domain classes (`Groups`, `Sensors`, `Controls`, `Enums`, `Events`, `Interface`, `Settings`, `Utils`).
|
||||
- `Prism.Ioc`, `Prism.Events`: For `IEventAggregator`, `ContainerLocator`, and event publication/subscription (`ListViewStatusEvent`, `GroupChannelDeleteRequestEvent`, `PageNavigationRequestEvent`).
|
||||
- WPF namespaces (`System.Windows.*`): For `ListView`, `DragEventArgs`, `Hyperlink`, etc.
|
||||
|
||||
**Key External Dependencies (inferred):**
|
||||
- `GroupChannelListViewModel`: Required as `DataContext` for all interactive logic.
|
||||
- `IGroupChannel`: Interface implemented by channel objects (e.g., `GroupChannel`).
|
||||
- `AutoSizedGridView`: Custom WPF control (from `DTS.Common.Controls`) used as `ChannelListListView.View`.
|
||||
- `MouseUtilities`: Used in `IsMouseOverTarget()` for drag-drop hit-testing (from `DTS.Common.Utils`).
|
||||
- `DTS.SensorDB.SoftwareFilter`: Used in `ISOCode_LostFocus` to fetch filter classes.
|
||||
- Global settings via `SettingsDB.GetGlobalValueBool("ShowGroups", true)`.
|
||||
|
||||
**Depended upon by:**
|
||||
- `GroupChannelListViewModel` (via `IGroupChannelListView` interface).
|
||||
- Event handlers (`ListViewStatusEvent`, `GroupChannelDeleteRequestEvent`, `PageNavigationRequestEvent`) suggest integration with broader Prism-based navigation and state management.
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **Silent failures**: Most event handlers and property getters return early if `DataContext` is `null` or of incorrect type (e.g., `Clear_Click`, `Delete_Click`, `MoveUp_Click`, `HandleColumns`). No exceptions or logging occur—debugging requires inspecting call stacks.
|
||||
- **Drag-drop modifier key handling is fragile**:
|
||||
- `ALT`/`CTRL` key states are checked via bitwise operations on `DragDropKeyStates`, but formats are mutated *in-place* (e.g., `"ALT_FORMAT"`), which may cause issues if `e.Data.GetFormats()` is called multiple times.
|
||||
- `TextBox_Drop` and `ChannelList_Drop` duplicate logic for format handling—risk of divergence if updated in one place but not the other.
|
||||
- **`ReadOnlyChannelsMode` is read-only and computed**: It does not raise change notifications; UI consumers must re-query it when `DataContext` changes.
|
||||
- **`HandleColumns` assumes `ChannelListListView.View` is always `AutoSizedGridView`**: If the view is changed (e.g., to `GridView`), column operations will silently fail.
|
||||
- **`MoveUp`/`MoveDown` via keyboard (Alt+↑/↓) uses `ChannelListListView.SelectedItems` order**, but `GetSelectedChannelsOrdered()` sorts by *view index*—this may differ from selection order if items are selected non-contiguously.
|
||||
- **`ISOCode_LostFocus` mutates `FilterClass` based on ISO code**, but only if `UseISOCodeFilterMapping` is `true`. No fallback or error handling if `GetFilterClassFromISOCode` fails.
|
||||
- **`Delete_Click` allows deletion of blank channels with valid orders** (per issue #14546), but blocks deletion if order ≤ 0—this may confuse users expecting blank channels to be deletable unconditionally.
|
||||
- **`TextBoxSourceUpdated` handles group name changes**, but the comment implies complex group reorganization logic in `GroupNameChanged`—behavior is not visible in this file.
|
||||
|
||||
*None identified from source alone.*
|
||||
@@ -0,0 +1,209 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Groups/GroupChannelList/ViewModel/GroupChannelListViewModel.cs
|
||||
generated_at: "2026-04-16T04:46:34.697931+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "7af2406ccff6580f"
|
||||
---
|
||||
|
||||
# ViewModel
|
||||
|
||||
**Documentation Page: `GroupChannelListViewModel`**
|
||||
|
||||
---
|
||||
|
||||
### **1. Purpose**
|
||||
|
||||
The `GroupChannelListViewModel` class serves as the core view model for managing channel assignments within the *GroupChannelList* UI module. It orchestrates the display, editing, and synchronization of channel data—linking logical channel definitions (e.g., ISO/user codes, sensor assignments, hardware mappings) to physical test hardware and sensor metadata. It supports operations such as bulk import via text paste, drag-and-drop assignment of sensors and hardware channels, range synchronization across channels on the same DAS, and real-time filtering/sorting. It acts as the intermediary between the view (`IGroupChannelListView`, `IGroupChannelSettingsListView`) and domain models (`IGroup`, `ITestSetup`, `ISensorData`, `IHardwareChannel`), publishing events for UI updates and system-wide state changes.
|
||||
|
||||
---
|
||||
|
||||
### **2. Public Interface**
|
||||
|
||||
#### **Constructor**
|
||||
```csharp
|
||||
public GroupChannelListViewModel(
|
||||
IGroupChannelListView view,
|
||||
IGroupChannelSettingsListView settingsView,
|
||||
IRegionManager regionManager,
|
||||
IEventAggregator eventAggregator,
|
||||
IUnityContainer unityContainer)
|
||||
```
|
||||
- Initializes the view model, wires up views, sets up interaction requests (`NotificationRequest`, `ConfirmationRequest`), and subscribes to events (`RaiseNotification`, `BusyIndicatorChangeNotification`, `TextPastedEvent`).
|
||||
- Initializes `SelectedChannelItems` as an `ObservableCollection<IGroupChannel>`.
|
||||
|
||||
#### **Properties**
|
||||
| Property | Type | Description |
|
||||
|---------|------|-------------|
|
||||
| `View` | `IGroupChannelListView` | Reference to the main channel list view. |
|
||||
| `SettingsView` | `IGroupChannelSettingsListView` | Reference to the channel settings view. |
|
||||
| `NotificationRequest` | `InteractionRequest<Notification>` | Prism interaction request for displaying notifications. |
|
||||
| `ConfirmationRequest` | `InteractionRequest<Confirmation>` | Prism interaction request for confirmation dialogs. |
|
||||
| `PropertyChanged` | `event PropertyChangedEventHandler` | Standard `INotifyPropertyChanged` event. |
|
||||
| `ChannelCount` | `int` | Derived from `AllChannels.Count`; triggers `GroupChannelsChangedEvent` on change. |
|
||||
| `AllChannels` | `IList<IGroupChannel>` | *Internal* full list of channels (including blank trailing channel). |
|
||||
| `Channels` | `IList<IGroupChannel>` | *Internal* list of non-blank channels (used for UI rendering). |
|
||||
| `SettingChannels` | `ObservableCollection<IGroupChannel>` | Sorted, filtered list of non-blank channels for settings view. |
|
||||
| `SelectedChannelItems` | `ObservableCollection<IGroupChannel>` | Currently selected channels (for multi-select operations). |
|
||||
| `SearchTerm` | `string` | Current search filter term. |
|
||||
| `BridgeFilter` | `PossibleFilters` | Bridge-type filter (e.g., `Analog`, `Squib`, `DigitalIn`). |
|
||||
| `UseTestSetupOrder` | `bool` | Whether channels are ordered by `TestSetupOrder` (vs `GroupChannelOrder`). |
|
||||
| `ISOViewMode` | `bool` | Controls display of ISO/user fields. |
|
||||
| `ShowSensorChannelUserValues` | `bool` | Controls visibility of sensor/user-specific fields. |
|
||||
| `AllowSensorPushAndPull` | `bool` | Enables sensor parameter comparison and push/pull UI. |
|
||||
| `UserIsAdmin` | `bool` | Admin status for permission checks. |
|
||||
| `AllowChannelDeletionByNonAdminUser` | `bool` | Whether non-admin users can delete channels. |
|
||||
| `AllowChannelDeletionFromFixedGroup` | `bool` | Whether channels in fixed groups can be deleted. |
|
||||
| `IsBusy` | `bool` | Bound to busy indicator via `BusyIndicatorChangeNotification`. |
|
||||
| `Group` | `IGroup` | *Set externally*; the group currently being edited. |
|
||||
| `TestSetup` | `ITestSetup` | *Set externally*; the test setup currently being edited. |
|
||||
| `Page` | `object` | *Set externally*; the page context (e.g., `GroupsPage`, `TestSetupsPage`). |
|
||||
|
||||
#### **Key Methods**
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `UpdateRangeLowG` | `public void UpdateRangeLowG(IGroupChannel channelChanged)` | Propagates `RangeLowG` to all other channels on the same DAS that have `RangeModifiableSensorLowG = true`. |
|
||||
| `UpdateRangeARS` | `public void UpdateRangeARS(IGroupChannel channelChanged)` | Propagates `Range` to all other channels on the same DAS that have `RangeModifiableSensorARS = true`. |
|
||||
| `UpdateACCouplingEnabled` | `public void UpdateACCouplingEnabled(IGroupChannel channelChanged)` | Propagates `ACCouplingEnabled` to other channels on the same DAS (casts to `GroupChannel`). |
|
||||
| `DoSensorAssignment` | `public void DoSensorAssignment(IGroupChannel groupChannel, IDragAndDropItem[] sensors)` | Assigns sensors to consecutive channels starting at `groupChannel`. Skips assignment to TSR-AIR channels (except StreamOut/UART). Adds new channels if needed. |
|
||||
| `DoHardwareAssignment` | `public void DoHardwareAssignment(IGroupChannel groupChannel, IHardwareChannel[] hardwareChannels)` | Assigns hardware channels to consecutive channels. Skips assignment to non-blank/non-StreamOut/UART channels if source is TSR-AIR. |
|
||||
| `OnTextPasted` | `public void OnTextPasted(ITextPastedEventArgs args)` | Handles paste events (ID = `GroupChannel.PASTE_ID`). Parses tab/semicolon/comma-delimited text into channels, inserting/updating starting at the sender’s position. |
|
||||
| `ParseText` | `private IEnumerable<IGroupChannel> ParseText(string text, object tag, out bool oneColumn)` | Parses raw text into `IGroupChannel` objects. Supports column mapping via `tag` (e.g., `"GroupName"`, `"ISOCode"`). Handles sensor/hardware lookup via dictionaries. |
|
||||
| `GetSensorSerialNumber` | `private string GetSensorSerialNumber(string channelSensor)` | Extracts serial number from sensor string (e.g., `"strain gauge 1 (SG1)"` → `"SG1"`). |
|
||||
| `CreateGroupIfNeeded` | `public IGroup CreateGroupIfNeeded(ITestSetup testSetup, string groupName)`<br>`private IGroup CreateGroupIfNeeded(string groupName)` | Creates a new group if none exists for `groupName` under `TestSetup`. |
|
||||
| `OnSetActive` | `public void OnSetActive()` | Called when view becomes active. Updates channel group names, compares sensor parameters (`CompareAndMarkChannelParameters`), refreshes view settings/columns, and resets sort/filter state. |
|
||||
| `CompareAndMarkChannelParameters` | `public bool CompareAndMarkChannelParameters(IGroupChannel ch)` | Compares channel parameters (e.g., `Range`, `FilterClass`, `SquibFireMode`) against sensor DB defaults. Marks channel as *different* if mismatched. Returns `true` if any change detected. |
|
||||
| `ResetSettingChannels` | `private void ResetSettingChannels()` | Rebuilds `SettingChannels` from `Channels`, applying sort (via `GroupChannelComparer`), filtering blanks, and setting `DigitalOutDurationMax` for TOM hardware. |
|
||||
| `Unset` | `public void Unset()` | Clears all internal state: `AllChannels`, `Channels`, sensor/hardware lookup dictionaries, filters. |
|
||||
| `ClearAllFilters` | `public void ClearAllFilters()` | Resets `SearchTerm`, `BridgeFilter`, `_filterByField`, `_dontFilterList`, and publishes `ListViewStatusEvent.Unloaded`. |
|
||||
| `PopulateChannels` | `public IDictionary<IGroup, IGroupChannel[]> PopulateChannels(...)` | **Core initialization method.** Loads channels from `Group` or `TestSetup`, populates lookup dictionaries (`_idToSensorDictionary`, `_displayToHardwareChannel`), sets up channel metadata (e.g., `RemoveSensorVisibility`, `DeleteShouldBeEnabled`), and returns `ChannelsForGroup` mapping. |
|
||||
| `MarkModified` | `public void MarkModified(IGroupChannel channel, bool bNotifyChanged = true)` | Handles adding a new blank channel after `channel` (if it’s the last non-blank), updates ordering, and ensures group assignment. |
|
||||
| `Remove` | `public void Remove(IGroupChannel channel, bool notifyChanged = true)` | Removes `channel`, adds a new blank channel if needed, updates group/channel mappings, and triggers `NotifyChannelsChanged`. |
|
||||
| `NotifyChannelsChanged` | `public void NotifyChannelsChanged()` | Publishes `PageModifiedEvent` and `GroupUpdatedEvent`, and updates `ChannelCount`/`AssignedPhysicalChannelCount`. |
|
||||
| `GroupNameChanged` | `public void GroupNameChanged(IGroupChannel channel)` | Updates `TestSetup.ChannelsForGroup` when a channel’s group name changes (removes from old group, adds to new). |
|
||||
| `ReportErrors` | `public void ReportErrors(string[] errors)` | Publishes `PageErrorEvent` with error messages. |
|
||||
| `Clear` | `public void Clear(IGroupChannel channel)` | Calls `channel.Clear()` (resets channel fields to defaults). |
|
||||
| `OnBusyIndicatorNotification` | `private void OnBusyIndicatorNotification(bool eventArg)` | Event handler for `BusyIndicatorChangeNotification`; sets `IsBusy`. |
|
||||
| `OnRaiseNotification` | `private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)` | Event handler for `RaiseNotification`; wraps message and title into `Notification` for UI. |
|
||||
|
||||
#### **Event Handlers (Private)**
|
||||
- `OnTextPasted`: Handles paste events.
|
||||
- `OnBusyIndicatorNotification`: Updates `IsBusy`.
|
||||
- `OnRaiseNotification`: Triggers `NotificationRequest`.
|
||||
|
||||
#### **Event Properties (Public)**
|
||||
- `PropertyChanged`: Standard property change notification.
|
||||
|
||||
---
|
||||
|
||||
### **3. Invariants**
|
||||
|
||||
- **Channel Ordering**:
|
||||
- `AllChannels` always ends with a blank `GroupChannel` (used for adding new channels).
|
||||
- `Channels` is a subset of `AllChannels` containing only non-blank channels.
|
||||
- Channel ordering is maintained via `TestSetupOrder` (if `UseTestSetupOrder`) or `GroupChannelOrder`.
|
||||
- `DetermineButtonState()` enforces `CanMoveUp`/`CanMoveDown` constraints (first channel cannot move up; last non-blank cannot move down).
|
||||
|
||||
- **Group/Hardware Consistency**:
|
||||
- Channels are associated with a `Group` (from `Group` or `TestSetup`) and `HardwareChannel`.
|
||||
- `GroupChannel.GroupName` must match `Group.DisplayName`.
|
||||
- Hardware assignments to TSR-AIR channels are restricted (only to blank, StreamOut, or UART channels).
|
||||
|
||||
- **Sensor/Hardware Lookup**:
|
||||
- `_idToSensorDictionary`, `_serialNumberToSensorDictionary`, and `_displayToHardwareChannel` must be populated before `PopulateChannels` completes.
|
||||
- Sensor serial numbers are extracted from strings (e.g., `"name (SN)"` → `"SN"`) using `GetSensorSerialNumber`.
|
||||
|
||||
- **Filtering**:
|
||||
- `_dontFilterList` preserves channels during filtering (e.g., after drag/drop or paste).
|
||||
- `Filter()` respects `BridgeFilter`, `SearchTerm`, and per-field filters (`_filterByField`).
|
||||
|
||||
- **Notification & Events**:
|
||||
- `OnPropertyChanged("ChannelCount")` triggers `GroupChannelsChangedEvent`.
|
||||
- `MarkModified`, `Remove`, `NotifyChannelsChanged` publish `PageModifiedEvent` and `GroupUpdatedEvent`.
|
||||
|
||||
---
|
||||
|
||||
### **4. Dependencies**
|
||||
|
||||
#### **External Dependencies (Imports/Usings)**
|
||||
- **Prism Framework**: `IEventAggregator`, `IRegionManager`, `UnityContainer`, `InteractionRequest<T>`, `DelegateCommand`.
|
||||
- **DTS Common Libraries**:
|
||||
- `DTS.Common.Classes.Groups`
|
||||
- `DTS.Common.Enums` (e.g., `PossibleFilters`, `Fields`, `HardwareTypes`)
|
||||
- `DTS.Common.Interface.*` (e.g., `IGroupChannel`, `ISensorData`, `IHardwareChannel`)
|
||||
- `DTS.Common.Events.*` (e.g., `TextPastedEvent`, `PageErrorEvent`)
|
||||
- `DTS.Common.Storage`, `DTS.Common.Converters`, `DTS.Common.Interactivity`
|
||||
|
||||
#### **Key Dependencies**
|
||||
- **Views**: `IGroupChannelListView`, `IGroupChannelSettingsListView`.
|
||||
- **Services**: `IEventAggregator`, `IUnityContainer`, `IRegionManager`.
|
||||
- **Data Sources**: `ITestSetup`, `IGroup`, `ISensorData`, `IDASHardware`, `IChannelSetting`.
|
||||
- **Events Published**:
|
||||
- `GroupChannelsChangedEvent`
|
||||
- `PageModifiedEvent`
|
||||
- `GroupUpdatedEvent`
|
||||
- `PageErrorEvent`
|
||||
- `ListViewStatusEvent`
|
||||
- `AppStatusEvent`
|
||||
- `RaiseNotification`
|
||||
|
||||
#### **Dependents**
|
||||
- `GroupChannelList` view (binds to `View`, `SettingsView`).
|
||||
- Other modules via `GroupChannelsChangedEvent`, `PageModifiedEvent`, `GroupUpdatedEvent`.
|
||||
|
||||
---
|
||||
|
||||
### **5. Gotchas**
|
||||
|
||||
- **TSR-AIR Channel Restrictions**:
|
||||
- Sensor/hardware assignments are blocked for non-StreamOut/UART TSR-AIR channels (see `DoSensorAssignment`, `DoHardwareAssignment`).
|
||||
- Embedded sensors in TSR-AIR units are only added if the unit is not already in the group.
|
||||
|
||||
- **Blank Channel Handling**:
|
||||
- `AllChannels` always ends with a blank channel; `Channels` excludes it.
|
||||
- `MarkModified` and `Remove` manage blank channel insertion/removal to maintain this invariant.
|
||||
|
||||
- **Paste Parsing Ambiguity**:
|
||||
- `ParseText` splits on `,`, `\t`, or `;` (in order) if tokens < 2. Column mapping depends on `tag` (e.g., `"GroupName"`).
|
||||
- `oneColumn` output indicates if only one column was present (used for single-field pastes).
|
||||
|
||||
- **Sensor Serial Number Parsing**:
|
||||
- `GetSensorSerialNumber` assumes serial numbers are enclosed in parentheses (e.g., `"name (SN)"`). If no parentheses, the entire string is used.
|
||||
|
||||
- **Group Name Changes**:
|
||||
- `GroupNameChanged` modifies `TestSetup.ChannelsForGroup` and may remove empty groups. Does *not* publish `PageModifiedEvent` (commented out).
|
||||
|
||||
- **Filtering Behavior**:
|
||||
- `_dontFilterList` is cleared on user-initiated filter changes (`initiatedByUser = true`).
|
||||
- Per-field filters (`_filterByField`) are applied *after* `BridgeFilter` and `SearchTerm`.
|
||||
|
||||
- **Hardware Channel Lookup**:
|
||||
- `_displayToHardwareChannel` uses `channel.ToString(hardware)` as the key (implementation-dependent string representation).
|
||||
|
||||
- **Sensor Constants**:
|
||||
- `CompareAndMarkChannelParameters` skips comparison for test-specific sensors (e.g., `TEST_SPECIFIC_ANALOG_SERIAL`).
|
||||
|
||||
- **Settings View Loading**:
|
||||
- `SettingsViewLoaded` controls whether `SettingChannels` triggers `OnPropertyChanged`.
|
||||
- `SettingChannelsLoaded` publishes `AppStatusEvent` (Busy → Available) during UI initialization.
|
||||
|
||||
- **No-Op Initialization Methods**:
|
||||
- `Initialize`, `InitializeAsync`, `Activated`, `Cleanup`, `CleanupAsync` are stubbed (no implementation).
|
||||
|
||||
- **Range Propagation Scope**:
|
||||
- `UpdateRangeLowG`/`UpdateRangeARS` only propagate within the same `DASId`.
|
||||
- `UpdateACCouplingEnabled` requires `GroupChannel` cast (runtime risk if non-`GroupChannel` instances exist).
|
||||
|
||||
- **Channel Ordering After Paste**:
|
||||
- After paste, `AllChannels[i].TestSetupOrder`/`GroupChannelOrder` is reset to `1 + i` for all non-blank channels.
|
||||
|
||||
- **Resource Strings**:
|
||||
- Uses `Resources.StringResources.TestChannelsGroupName` for default group names in `TestSetup` mode.
|
||||
|
||||
- **Missing Validation**:
|
||||
- `ParseText` does not validate sensor/hardware references beyond existence in dictionaries (e.g., invalid IDs are logged but do not halt processing).
|
||||
|
||||
---
|
||||
|
||||
*Note: All behaviors are derived strictly from the provided source. No external documentation or runtime behavior was assumed.*
|
||||
Reference in New Issue
Block a user