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

101 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/Modules/ISO/ExtraProperties/Model/ExtraPropertyModel.cs
generated_at: "2026-04-16T04:39:00.347162+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "f8c9e5793048774d"
---
# Model
### **Purpose**
This module implements the `ExtraPropertyModel` class, a concrete data model for representing key-value pairs (e.g., ISO channel codes and names or user-defined properties) within a WPF-based UI, conforming to the `IExtraProperty` interface. It supports property change notifications via Prisms `BasePropertyChanged`, integrates with Prisms event aggregation system for cross-module communication (e.g., signaling page modifications or paste events), and provides a custom `PasteCommand` to handle clipboard paste operations with special handling for multi-line or multi-field text. Its role is to serve as the view-model backing for UI controls that edit extra properties in ISO data contexts.
---
### **Public Interface**
#### **`ExtraPropertyModel` class**
- **`public ExtraPropertyModel(IExtraProperty extraProperty)`**
Initializes a new instance by copying `Key` and `Value` from an existing `IExtraProperty` instance. Registers paste commands during construction.
- **`public ExtraPropertyModel()`**
Default constructor. Registers paste commands. `Key` and `Value` are initialized to `null`.
- **`public ExtraPropertyModel(KeyValuePair<string, string> extraProperty)`**
Initializes a new instance using a `KeyValuePair<string, string>`. Registers paste commands.
- **`public UIItemStatus ItemStatus { get; set; }`**
Gets or sets the UI status of the item (e.g., `None`, `Added`, `Modified`, `Deleted`). Backed by `SetProperty` for change notifications.
- **`public string Key { get; set; }`**
Gets or sets the code (e.g., ISO code or user code). Backed by `SetProperty`.
- **`public string Value { get; set; }`**
Gets or sets the associated name (e.g., ISO channel name or user channel name). Backed by `SetProperty`.
- **`public ICommand PasteCommand { get; set; }`**
Exposes the command bound to paste operations. Initialized to a `PasteCommandClass` instance with `PASTE_ID = "ExtraProperty"`.
- **`public const string PASTE_ID = "ExtraProperty"`**
Constant identifier used to distinguish paste operations originating from this model.
#### **`PasteCommandClass` class**
- **`public string Id { get; }`**
Gets the command ID passed during construction (e.g., `"ExtraProperty"`).
- **`public bool CanExecute(object parameter)`**
Always returns `true`.
- **`public void Execute(object parameter)`**
Handles paste logic:
- Validates `parameter` is a `TextBox`.
- Attempts to resolve `IExtraProperty` from `TextBox.DataContext`, falling back to `ChannelCodeBuilder` or `ChannelNameBuilder` contexts.
- Checks clipboard contains text.
- If clipboard text has exactly one line and contains no delimiters (`','`, `';'`, `'\t'`), publishes `PageModifiedEvent` and exits early (single-field paste is handled by `TextChanged`).
- Otherwise, clears `Key`/`Value` on the target `IExtraProperty` (a no-op assignment to trigger change tracking), then publishes `TextPastedEvent` with the raw text, target property, command ID, and `TextBox.Tag`.
- On exception, publishes `PageErrorEvent` with the exception message.
- **`public event EventHandler CanExecuteChanged`**
Required by `ICommand`, but never raised (no-op).
- **`public PasteCommandClass(string id)`**
Constructor storing `id` in `Id`.
---
### **Invariants**
- `Key` and `Value` may be `null`; no validation is enforced on their values.
- `ItemStatus` defaults to `UIItemStatus.None` and must be explicitly set by consumers.
- The `PasteCommand` is registered globally via `CommandManager.RegisterClassCommandBinding`, meaning it applies to *all* instances of `ExtraPropertyModel` and its subclasses.
- The `Paste` method (private) is never implemented — it is a stub. Actual paste behavior resides entirely in `PasteCommandClass.Execute`.
- `CanExecuteChanged` is never raised by `PasteCommandClass`, so WPF command bindings may not update UI state (e.g., button enablement) dynamically.
---
### **Dependencies**
- **Imports/Usings**:
- `DTS.Common.ISO.ExtraProperties` → Provides `IExtraProperty` interface.
- `DTS.Common.Controls` → Provides `ChannelCodeBuilder`, `ChannelNameBuilder` types.
- `DTS.Common.Enums` → Provides `UIItemStatus`.
- `DTS.Common.Events` → Provides `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent`, and their argument types.
- `Prism.Ioc` → Provides `ContainerLocator` (for resolving `IEventAggregator`).
- `Prism.Events` → Provides `IEventAggregator`.
- **Depended upon**:
- `IExtraProperty` interface (consumed via constructor and paste logic).
- `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent` (published by `PasteCommandClass`).
- `ContainerLocator.Container` (runtime dependency for event aggregation).
---
### **Gotchas**
- **`Paste` method is empty**: The private `Paste(object sender, ExecutedRoutedEventArgs e)` method is declared but has no implementation; all logic resides in `PasteCommandClass.Execute`. This is likely intentional (to satisfy `CommandBinding` requirements), but may confuse readers.
- **`CanExecuteChanged` is never raised**: `PasteCommandClass` implements `ICommand` but does not notify subscribers of `CanExecute` state changes, potentially causing stale UI (e.g., disabled paste buttons).
- **Ambiguous paste behavior**:
- Single-line, non-delimited text triggers `PageModifiedEvent` but *not* `TextPastedEvent`, while multi-line or delimited text triggers `TextPastedEvent` but *not* `PageModifiedEvent`. This asymmetry may lead to inconsistent state tracking.
- The "wipe out built-in effect" assignment (`extraProperty.Key = extraProperty.Key`) is a no-op and serves no functional purpose beyond triggering change notifications if the property setter is implemented non-trivially elsewhere.
- **Clipboard access without safety checks**: `Clipboard.GetText()` may throw exceptions (e.g., in sandboxed environments), but only generic `Exception` handling is present.
- **No null-safety for `tb.Tag`**: The `tb.Tag` value is passed directly in `TextPastedArgs` without null checks.
- **Tight coupling to Prism**: Reliance on `ContainerLocator.Container` for `IEventAggregator` makes unit testing difficult without Prism infrastructure.
- **No cleanup in constructors**: While the finalizer attempts to null `_key`/`_value`, this is unreliable and unnecessary in modern .NET (where `IDisposable` would be preferred if unmanaged resources were involved — none are evident here).